diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/doc.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/doc.go new file mode 100644 index 0000000000..030287cd80 --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/doc.go @@ -0,0 +1 @@ +package sandboxspec diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.pb.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.pb.go new file mode 100644 index 0000000000..f164027d9b --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.pb.go @@ -0,0 +1,2228 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.7 +// protoc v5.26.0 +// source: github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.proto + +package sandboxspec + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RegistryHive int32 + +const ( + RegistryHive_REGISTRY_HIVE_SYSTEM RegistryHive = 0 + RegistryHive_REGISTRY_HIVE_SOFTWARE RegistryHive = 1 + RegistryHive_REGISTRY_HIVE_SECURITY RegistryHive = 2 + RegistryHive_REGISTRY_HIVE_SAM RegistryHive = 3 +) + +// Enum value maps for RegistryHive. +var ( + RegistryHive_name = map[int32]string{ + 0: "REGISTRY_HIVE_SYSTEM", + 1: "REGISTRY_HIVE_SOFTWARE", + 2: "REGISTRY_HIVE_SECURITY", + 3: "REGISTRY_HIVE_SAM", + } + RegistryHive_value = map[string]int32{ + "REGISTRY_HIVE_SYSTEM": 0, + "REGISTRY_HIVE_SOFTWARE": 1, + "REGISTRY_HIVE_SECURITY": 2, + "REGISTRY_HIVE_SAM": 3, + } +) + +func (x RegistryHive) Enum() *RegistryHive { + p := new(RegistryHive) + *p = x + return p +} + +func (x RegistryHive) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RegistryHive) Descriptor() protoreflect.EnumDescriptor { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[0].Descriptor() +} + +func (RegistryHive) Type() protoreflect.EnumType { + return &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[0] +} + +func (x RegistryHive) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RegistryHive.Descriptor instead. +func (RegistryHive) EnumDescriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{0} +} + +type RegistryValueType int32 + +const ( + RegistryValueType_REGISTRY_VALUE_TYPE_NONE RegistryValueType = 0 + RegistryValueType_REGISTRY_VALUE_TYPE_STRING RegistryValueType = 1 + RegistryValueType_REGISTRY_VALUE_TYPE_EXPANDED_STRING RegistryValueType = 2 + RegistryValueType_REGISTRY_VALUE_TYPE_MULTI_STRING RegistryValueType = 3 + RegistryValueType_REGISTRY_VALUE_TYPE_BINARY RegistryValueType = 4 + RegistryValueType_REGISTRY_VALUE_TYPE_D_WORD RegistryValueType = 5 + RegistryValueType_REGISTRY_VALUE_TYPE_Q_WORD RegistryValueType = 6 + RegistryValueType_REGISTRY_VALUE_TYPE_CUSTOM_TYPE RegistryValueType = 7 +) + +// Enum value maps for RegistryValueType. +var ( + RegistryValueType_name = map[int32]string{ + 0: "REGISTRY_VALUE_TYPE_NONE", + 1: "REGISTRY_VALUE_TYPE_STRING", + 2: "REGISTRY_VALUE_TYPE_EXPANDED_STRING", + 3: "REGISTRY_VALUE_TYPE_MULTI_STRING", + 4: "REGISTRY_VALUE_TYPE_BINARY", + 5: "REGISTRY_VALUE_TYPE_D_WORD", + 6: "REGISTRY_VALUE_TYPE_Q_WORD", + 7: "REGISTRY_VALUE_TYPE_CUSTOM_TYPE", + } + RegistryValueType_value = map[string]int32{ + "REGISTRY_VALUE_TYPE_NONE": 0, + "REGISTRY_VALUE_TYPE_STRING": 1, + "REGISTRY_VALUE_TYPE_EXPANDED_STRING": 2, + "REGISTRY_VALUE_TYPE_MULTI_STRING": 3, + "REGISTRY_VALUE_TYPE_BINARY": 4, + "REGISTRY_VALUE_TYPE_D_WORD": 5, + "REGISTRY_VALUE_TYPE_Q_WORD": 6, + "REGISTRY_VALUE_TYPE_CUSTOM_TYPE": 7, + } +) + +func (x RegistryValueType) Enum() *RegistryValueType { + p := new(RegistryValueType) + *p = x + return p +} + +func (x RegistryValueType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RegistryValueType) Descriptor() protoreflect.EnumDescriptor { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[1].Descriptor() +} + +func (RegistryValueType) Type() protoreflect.EnumType { + return &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[1] +} + +func (x RegistryValueType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RegistryValueType.Descriptor instead. +func (RegistryValueType) EnumDescriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{1} +} + +type PreferredRootFSType int32 + +const ( + PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD PreferredRootFSType = 0 + PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_VHD PreferredRootFSType = 1 +) + +// Enum value maps for PreferredRootFSType. +var ( + PreferredRootFSType_name = map[int32]string{ + 0: "PREFERRED_ROOT_FS_TYPE_INITRD", + 1: "PREFERRED_ROOT_FS_TYPE_VHD", + } + PreferredRootFSType_value = map[string]int32{ + "PREFERRED_ROOT_FS_TYPE_INITRD": 0, + "PREFERRED_ROOT_FS_TYPE_VHD": 1, + } +) + +func (x PreferredRootFSType) Enum() *PreferredRootFSType { + p := new(PreferredRootFSType) + *p = x + return p +} + +func (x PreferredRootFSType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PreferredRootFSType) Descriptor() protoreflect.EnumDescriptor { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[2].Descriptor() +} + +func (PreferredRootFSType) Type() protoreflect.EnumType { + return &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes[2] +} + +func (x PreferredRootFSType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PreferredRootFSType.Descriptor instead. +func (PreferredRootFSType) EnumDescriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{2} +} + +type Specs struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Sandbox isolation mode. + // + // Types that are valid to be assigned to IsolationLevel: + // + // *Specs_Process + // *Specs_Hypervisor + IsolationLevel isSpecs_IsolationLevel `protobuf_oneof:"isolation_level"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Specs) Reset() { + *x = Specs{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Specs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Specs) ProtoMessage() {} + +func (x *Specs) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Specs.ProtoReflect.Descriptor instead. +func (*Specs) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{0} +} + +func (x *Specs) GetIsolationLevel() isSpecs_IsolationLevel { + if x != nil { + return x.IsolationLevel + } + return nil +} + +func (x *Specs) GetProcess() *ProcessIsolated { + if x != nil { + if x, ok := x.IsolationLevel.(*Specs_Process); ok { + return x.Process + } + } + return nil +} + +func (x *Specs) GetHypervisor() *HypervisorIsolated { + if x != nil { + if x, ok := x.IsolationLevel.(*Specs_Hypervisor); ok { + return x.Hypervisor + } + } + return nil +} + +type isSpecs_IsolationLevel interface { + isSpecs_IsolationLevel() +} + +type Specs_Process struct { + // Process-isolated sandbox (no UVM). + Process *ProcessIsolated `protobuf:"bytes,1,opt,name=process,proto3,oneof"` +} + +type Specs_Hypervisor struct { + // Hypervisor-isolated sandbox (UVM-backed). + Hypervisor *HypervisorIsolated `protobuf:"bytes,2,opt,name=hypervisor,proto3,oneof"` +} + +func (*Specs_Process) isSpecs_IsolationLevel() {} + +func (*Specs_Hypervisor) isSpecs_IsolationLevel() {} + +type ProcessIsolated struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessIsolated) Reset() { + *x = ProcessIsolated{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessIsolated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessIsolated) ProtoMessage() {} + +func (x *ProcessIsolated) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProcessIsolated.ProtoReflect.Descriptor instead. +func (*ProcessIsolated) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{1} +} + +type HypervisorIsolated struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Platform-specific UVM options. + // + // Types that are valid to be assigned to Platform: + // + // *HypervisorIsolated_Lcow + // *HypervisorIsolated_Wcow + Platform isHypervisorIsolated_Platform `protobuf_oneof:"platform"` + // UVM CPU topology. + CpuConfig *CPUConfig `protobuf:"bytes,3,opt,name=cpuConfig,proto3" json:"cpuConfig,omitempty"` + // UVM memory sizing and commit policy; MMIO aperture tuning. + MemoryConfig *MemoryConfig `protobuf:"bytes,4,opt,name=memoryConfig,proto3" json:"memoryConfig,omitempty"` + // UVM storage QoS caps and file-share hardening. + StorageConfig *StorageConfig `protobuf:"bytes,5,opt,name=storageConfig,proto3" json:"storageConfig,omitempty"` + // UVM vNUMA hints (implicit/explicit topology). + NumaConfig *NUMAConfig `protobuf:"bytes,6,opt,name=numaConfig,proto3" json:"numaConfig,omitempty"` + // Misc sandbox controls: networking proxy, dump paths, HvSocket services, console pipe. + AdditionalConfig *AdditionalConfig `protobuf:"bytes,7,opt,name=additionalConfig,proto3" json:"additionalConfig,omitempty"` + // Assign the UVM to a CPU group. Mutually exclusive with resource_partition_id. + CpuGroupID *string `protobuf:"bytes,8,opt,name=cpu_group_id,json=cpuGroupId,proto3,oneof" json:"cpu_group_id,omitempty"` + // Resource partition GUID to associate the UVM with (has its own CPU group). + // Mutually exclusive with cpu_group_id. + ResourcePartitionID *string `protobuf:"bytes,9,opt,name=resource_partition_id,json=resourcePartitionId,proto3,oneof" json:"resource_partition_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HypervisorIsolated) Reset() { + *x = HypervisorIsolated{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HypervisorIsolated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HypervisorIsolated) ProtoMessage() {} + +func (x *HypervisorIsolated) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HypervisorIsolated.ProtoReflect.Descriptor instead. +func (*HypervisorIsolated) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{2} +} + +func (x *HypervisorIsolated) GetPlatform() isHypervisorIsolated_Platform { + if x != nil { + return x.Platform + } + return nil +} + +func (x *HypervisorIsolated) GetLcow() *LinuxHyperVOptions { + if x != nil { + if x, ok := x.Platform.(*HypervisorIsolated_Lcow); ok { + return x.Lcow + } + } + return nil +} + +func (x *HypervisorIsolated) GetWcow() *WindowsHyperVOptions { + if x != nil { + if x, ok := x.Platform.(*HypervisorIsolated_Wcow); ok { + return x.Wcow + } + } + return nil +} + +func (x *HypervisorIsolated) GetCpuConfig() *CPUConfig { + if x != nil { + return x.CpuConfig + } + return nil +} + +func (x *HypervisorIsolated) GetMemoryConfig() *MemoryConfig { + if x != nil { + return x.MemoryConfig + } + return nil +} + +func (x *HypervisorIsolated) GetStorageConfig() *StorageConfig { + if x != nil { + return x.StorageConfig + } + return nil +} + +func (x *HypervisorIsolated) GetNumaConfig() *NUMAConfig { + if x != nil { + return x.NumaConfig + } + return nil +} + +func (x *HypervisorIsolated) GetAdditionalConfig() *AdditionalConfig { + if x != nil { + return x.AdditionalConfig + } + return nil +} + +func (x *HypervisorIsolated) GetCpuGroupID() string { + if x != nil && x.CpuGroupID != nil { + return *x.CpuGroupID + } + return "" +} + +func (x *HypervisorIsolated) GetResourcePartitionID() string { + if x != nil && x.ResourcePartitionID != nil { + return *x.ResourcePartitionID + } + return "" +} + +type isHypervisorIsolated_Platform interface { + isHypervisorIsolated_Platform() +} + +type HypervisorIsolated_Lcow struct { + // Linux UVM options. + Lcow *LinuxHyperVOptions `protobuf:"bytes,1,opt,name=lcow,proto3,oneof"` +} + +type HypervisorIsolated_Wcow struct { + // Windows UVM options. + Wcow *WindowsHyperVOptions `protobuf:"bytes,2,opt,name=wcow,proto3,oneof"` +} + +func (*HypervisorIsolated_Lcow) isHypervisorIsolated_Platform() {} + +func (*HypervisorIsolated_Wcow) isHypervisorIsolated_Platform() {} + +type CPUConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // vCPU count override for the UVM. On UVM, count/limit/weight may be combined. + ProcessorCount *int32 `protobuf:"varint,1,opt,name=processor_count,json=processorCount,proto3,oneof" json:"processor_count,omitempty"` + // vCPU percentage cap: 1..100000 (100000 = 100%). Omitted => platform default. + ProcessorLimit *int32 `protobuf:"varint,2,opt,name=processor_limit,json=processorLimit,proto3,oneof" json:"processor_limit,omitempty"` + // vCPU scheduling weight: 0..10000 (100 default). Omitted => default. + ProcessorWeight *int32 `protobuf:"varint,3,opt,name=processor_weight,json=processorWeight,proto3,oneof" json:"processor_weight,omitempty"` + // architecture represents the architecture of the platform. + Architecture *string `protobuf:"bytes,4,opt,name=architecture,proto3,oneof" json:"architecture,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CPUConfig) Reset() { + *x = CPUConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CPUConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CPUConfig) ProtoMessage() {} + +func (x *CPUConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CPUConfig.ProtoReflect.Descriptor instead. +func (*CPUConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{3} +} + +func (x *CPUConfig) GetProcessorCount() int32 { + if x != nil && x.ProcessorCount != nil { + return *x.ProcessorCount + } + return 0 +} + +func (x *CPUConfig) GetProcessorLimit() int32 { + if x != nil && x.ProcessorLimit != nil { + return *x.ProcessorLimit + } + return 0 +} + +func (x *CPUConfig) GetProcessorWeight() int32 { + if x != nil && x.ProcessorWeight != nil { + return *x.ProcessorWeight + } + return 0 +} + +func (x *CPUConfig) GetArchitecture() string { + if x != nil && x.Architecture != nil { + return *x.Architecture + } + return "" +} + +type MemoryConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Total UVM memory size in MB (MB units; OCI uses bytes). + MemorySizeInMb *uint64 `protobuf:"varint,1,opt,name=memory_size_in_mb,json=memorySizeInMb,proto3,oneof" json:"memory_size_in_mb,omitempty"` + // MMIO aperture tuning (low gap/base/high gap in MB). + LowMmioGapInMb *uint64 `protobuf:"varint,2,opt,name=low_mmio_gap_in_mb,json=lowMmioGapInMb,proto3,oneof" json:"low_mmio_gap_in_mb,omitempty"` + HighMmioBaseInMb *uint64 `protobuf:"varint,3,opt,name=high_mmio_base_in_mb,json=highMmioBaseInMb,proto3,oneof" json:"high_mmio_base_in_mb,omitempty"` + HighMmioGapInMb *uint64 `protobuf:"varint,4,opt,name=high_mmio_gap_in_mb,json=highMmioGapInMb,proto3,oneof" json:"high_mmio_gap_in_mb,omitempty"` + // Allow virtual memory overcommit (true by default). Set false for fully physical backing. + AllowOvercommit *bool `protobuf:"varint,5,opt,name=allow_overcommit,json=allowOvercommit,proto3,oneof" json:"allow_overcommit,omitempty"` + // Enforce fully physically backed memory, including future device additions. + FullyPhysicallyBacked *bool `protobuf:"varint,6,opt,name=fully_physically_backed,json=fullyPhysicallyBacked,proto3,oneof" json:"fully_physically_backed,omitempty"` + // Enable deferred commit for virtual memory (defaults to false). + EnableDeferredCommit *bool `protobuf:"varint,7,opt,name=enable_deferred_commit,json=enableDeferredCommit,proto3,oneof" json:"enable_deferred_commit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MemoryConfig) Reset() { + *x = MemoryConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MemoryConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemoryConfig) ProtoMessage() {} + +func (x *MemoryConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemoryConfig.ProtoReflect.Descriptor instead. +func (*MemoryConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{4} +} + +func (x *MemoryConfig) GetMemorySizeInMb() uint64 { + if x != nil && x.MemorySizeInMb != nil { + return *x.MemorySizeInMb + } + return 0 +} + +func (x *MemoryConfig) GetLowMmioGapInMb() uint64 { + if x != nil && x.LowMmioGapInMb != nil { + return *x.LowMmioGapInMb + } + return 0 +} + +func (x *MemoryConfig) GetHighMmioBaseInMb() uint64 { + if x != nil && x.HighMmioBaseInMb != nil { + return *x.HighMmioBaseInMb + } + return 0 +} + +func (x *MemoryConfig) GetHighMmioGapInMb() uint64 { + if x != nil && x.HighMmioGapInMb != nil { + return *x.HighMmioGapInMb + } + return 0 +} + +func (x *MemoryConfig) GetAllowOvercommit() bool { + if x != nil && x.AllowOvercommit != nil { + return *x.AllowOvercommit + } + return false +} + +func (x *MemoryConfig) GetFullyPhysicallyBacked() bool { + if x != nil && x.FullyPhysicallyBacked != nil { + return *x.FullyPhysicallyBacked + } + return false +} + +func (x *MemoryConfig) GetEnableDeferredCommit() bool { + if x != nil && x.EnableDeferredCommit != nil { + return *x.EnableDeferredCommit + } + return false +} + +type StorageConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Max storage IOPS; 0/omitted => platform default. + StorageQosIopsMaximum *int32 `protobuf:"varint,1,opt,name=storage_qos_iops_maximum,json=storageQosIopsMaximum,proto3,oneof" json:"storage_qos_iops_maximum,omitempty"` + // Max storage bandwidth in bytes/sec; 0/omitted => platform default. + StorageQosBandwidthMaximum *int32 `protobuf:"varint,2,opt,name=storage_qos_bandwidth_maximum,json=storageQosBandwidthMaximum,proto3,oneof" json:"storage_qos_bandwidth_maximum,omitempty"` + // Disallow any writable file shares (e.g., VSMB/Plan9) to the UVM. + NoWritableFileShares *bool `protobuf:"varint,3,opt,name=no_writable_file_shares,json=noWritableFileShares,proto3,oneof" json:"no_writable_file_shares,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StorageConfig) Reset() { + *x = StorageConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StorageConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StorageConfig) ProtoMessage() {} + +func (x *StorageConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StorageConfig.ProtoReflect.Descriptor instead. +func (*StorageConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{5} +} + +func (x *StorageConfig) GetStorageQosIopsMaximum() int32 { + if x != nil && x.StorageQosIopsMaximum != nil { + return *x.StorageQosIopsMaximum + } + return 0 +} + +func (x *StorageConfig) GetStorageQosBandwidthMaximum() int32 { + if x != nil && x.StorageQosBandwidthMaximum != nil { + return *x.StorageQosBandwidthMaximum + } + return 0 +} + +func (x *StorageConfig) GetNoWritableFileShares() bool { + if x != nil && x.NoWritableFileShares != nil { + return *x.NoWritableFileShares + } + return false +} + +type NUMAConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Implicit vNUMA: max memory per node (MB). + MaxMemorySizePerNumaNode *uint64 `protobuf:"varint,1,opt,name=max_memory_size_per_numa_node,json=maxMemorySizePerNumaNode,proto3,oneof" json:"max_memory_size_per_numa_node,omitempty"` + // Implicit vNUMA: max processors per node. + MaxProcessorsPerNumaNode *uint32 `protobuf:"varint,2,opt,name=max_processors_per_numa_node,json=maxProcessorsPerNumaNode,proto3,oneof" json:"max_processors_per_numa_node,omitempty"` + // Implicit vNUMA: preferred physical NUMA nodes. + PreferredPhysicalNumaNodes []uint32 `protobuf:"varint,3,rep,packed,name=preferred_physical_numa_nodes,json=preferredPhysicalNumaNodes,proto3" json:"preferred_physical_numa_nodes,omitempty"` + // Explicit vNUMA: pNUMA -> vNUMA mapping by index. + NumaMappedPhysicalNodes []uint32 `protobuf:"varint,4,rep,packed,name=numa_mapped_physical_nodes,json=numaMappedPhysicalNodes,proto3" json:"numa_mapped_physical_nodes,omitempty"` + // Explicit vNUMA: processor counts per vNUMA index. + NumaProcessorCounts []uint32 `protobuf:"varint,5,rep,packed,name=numa_processor_counts,json=numaProcessorCounts,proto3" json:"numa_processor_counts,omitempty"` + // Explicit vNUMA: memory block counts per vNUMA index. + NumaMemoryBlocksCounts []uint64 `protobuf:"varint,6,rep,packed,name=numa_memory_blocks_counts,json=numaMemoryBlocksCounts,proto3" json:"numa_memory_blocks_counts,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NUMAConfig) Reset() { + *x = NUMAConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NUMAConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NUMAConfig) ProtoMessage() {} + +func (x *NUMAConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NUMAConfig.ProtoReflect.Descriptor instead. +func (*NUMAConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{6} +} + +func (x *NUMAConfig) GetMaxMemorySizePerNumaNode() uint64 { + if x != nil && x.MaxMemorySizePerNumaNode != nil { + return *x.MaxMemorySizePerNumaNode + } + return 0 +} + +func (x *NUMAConfig) GetMaxProcessorsPerNumaNode() uint32 { + if x != nil && x.MaxProcessorsPerNumaNode != nil { + return *x.MaxProcessorsPerNumaNode + } + return 0 +} + +func (x *NUMAConfig) GetPreferredPhysicalNumaNodes() []uint32 { + if x != nil { + return x.PreferredPhysicalNumaNodes + } + return nil +} + +func (x *NUMAConfig) GetNumaMappedPhysicalNodes() []uint32 { + if x != nil { + return x.NumaMappedPhysicalNodes + } + return nil +} + +func (x *NUMAConfig) GetNumaProcessorCounts() []uint32 { + if x != nil { + return x.NumaProcessorCounts + } + return nil +} + +func (x *NUMAConfig) GetNumaMemoryBlocksCounts() []uint64 { + if x != nil { + return x.NumaMemoryBlocksCounts + } + return nil +} + +type AdditionalConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // ncproxy service address for network setup; when set, use ncproxy. + NetworkConfigProxy *string `protobuf:"bytes,1,opt,name=network_config_proxy,json=networkConfigProxy,proto3,oneof" json:"network_config_proxy,omitempty"` + // In-guest path for container process dumps; prefer a mounted volume over scratch. + ProcessDumpLocation *string `protobuf:"bytes,2,opt,name=process_dump_location,json=processDumpLocation,proto3,oneof" json:"process_dump_location,omitempty"` + // Host directory to collect UVM crash dumps. + DumpDirectoryPath *string `protobuf:"bytes,3,opt,name=dump_directory_path,json=dumpDirectoryPath,proto3,oneof" json:"dump_directory_path,omitempty"` + // HvSocket per-service configuration (bind/connect SDDL, wildcard, disabled). + AdditionalHypervConfig map[string]*HvSocketServiceConfig `protobuf:"bytes,4,rep,name=additional_hyperv_config,json=additionalHypervConfig,proto3" json:"additional_hyperv_config,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Serial console named pipe (e.g., \\.\pipe\) for the UVM console. + ConsolePipe *string `protobuf:"bytes,5,opt,name=console_pipe,json=consolePipe,proto3,oneof" json:"console_pipe,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdditionalConfig) Reset() { + *x = AdditionalConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdditionalConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdditionalConfig) ProtoMessage() {} + +func (x *AdditionalConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdditionalConfig.ProtoReflect.Descriptor instead. +func (*AdditionalConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{7} +} + +func (x *AdditionalConfig) GetNetworkConfigProxy() string { + if x != nil && x.NetworkConfigProxy != nil { + return *x.NetworkConfigProxy + } + return "" +} + +func (x *AdditionalConfig) GetProcessDumpLocation() string { + if x != nil && x.ProcessDumpLocation != nil { + return *x.ProcessDumpLocation + } + return "" +} + +func (x *AdditionalConfig) GetDumpDirectoryPath() string { + if x != nil && x.DumpDirectoryPath != nil { + return *x.DumpDirectoryPath + } + return "" +} + +func (x *AdditionalConfig) GetAdditionalHypervConfig() map[string]*HvSocketServiceConfig { + if x != nil { + return x.AdditionalHypervConfig + } + return nil +} + +func (x *AdditionalConfig) GetConsolePipe() string { + if x != nil && x.ConsolePipe != nil { + return *x.ConsolePipe + } + return "" +} + +type HvSocketServiceConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Host bind permission SDDL. + BindSecurityDescriptor *string `protobuf:"bytes,1,opt,name=bind_security_descriptor,json=bindSecurityDescriptor,proto3,oneof" json:"bind_security_descriptor,omitempty"` + // Host connect permission SDDL. + ConnectSecurityDescriptor *string `protobuf:"bytes,2,opt,name=connect_security_descriptor,json=connectSecurityDescriptor,proto3,oneof" json:"connect_security_descriptor,omitempty"` + // Allow wildcard binds per policy. + AllowWildcardBinds *bool `protobuf:"varint,3,opt,name=allow_wildcard_binds,json=allowWildcardBinds,proto3,oneof" json:"allow_wildcard_binds,omitempty"` + // Disable service (refuse new, cancel existing connections). + Disabled *bool `protobuf:"varint,4,opt,name=disabled,proto3,oneof" json:"disabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HvSocketServiceConfig) Reset() { + *x = HvSocketServiceConfig{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HvSocketServiceConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HvSocketServiceConfig) ProtoMessage() {} + +func (x *HvSocketServiceConfig) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HvSocketServiceConfig.ProtoReflect.Descriptor instead. +func (*HvSocketServiceConfig) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{8} +} + +func (x *HvSocketServiceConfig) GetBindSecurityDescriptor() string { + if x != nil && x.BindSecurityDescriptor != nil { + return *x.BindSecurityDescriptor + } + return "" +} + +func (x *HvSocketServiceConfig) GetConnectSecurityDescriptor() string { + if x != nil && x.ConnectSecurityDescriptor != nil { + return *x.ConnectSecurityDescriptor + } + return "" +} + +func (x *HvSocketServiceConfig) GetAllowWildcardBinds() bool { + if x != nil && x.AllowWildcardBinds != nil { + return *x.AllowWildcardBinds + } + return false +} + +func (x *HvSocketServiceConfig) GetDisabled() bool { + if x != nil && x.Disabled != nil { + return *x.Disabled + } + return false +} + +type WindowsHyperVOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Boot configuration for WCOW UVM. + WindowsBootOptions *WindowsBootOptions `protobuf:"bytes,1,opt,name=windowsBootOptions,proto3" json:"windowsBootOptions,omitempty"` + // Guest configuration for WCOW UVM. + WindowsGuestOptions *WindowsGuestOptions `protobuf:"bytes,2,opt,name=windowsGuestOptions,proto3" json:"windowsGuestOptions,omitempty"` + // Confidential computing options for WCOW. + ConfidentialOptions *WCOWConfidentialOptions `protobuf:"bytes,3,opt,name=confidentialOptions,proto3" json:"confidentialOptions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WindowsHyperVOptions) Reset() { + *x = WindowsHyperVOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WindowsHyperVOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WindowsHyperVOptions) ProtoMessage() {} + +func (x *WindowsHyperVOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WindowsHyperVOptions.ProtoReflect.Descriptor instead. +func (*WindowsHyperVOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{9} +} + +func (x *WindowsHyperVOptions) GetWindowsBootOptions() *WindowsBootOptions { + if x != nil { + return x.WindowsBootOptions + } + return nil +} + +func (x *WindowsHyperVOptions) GetWindowsGuestOptions() *WindowsGuestOptions { + if x != nil { + return x.WindowsGuestOptions + } + return nil +} + +func (x *WindowsHyperVOptions) GetConfidentialOptions() *WCOWConfidentialOptions { + if x != nil { + return x.ConfidentialOptions + } + return nil +} + +type WindowsBootOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Disable network compartment namespacing in the WCOW UVM. + DisableCompartmentNamespace *bool `protobuf:"varint,1,opt,name=disable_compartment_namespace,json=disableCompartmentNamespace,proto3,oneof" json:"disable_compartment_namespace,omitempty"` + // Disable direct mapping for VSMB shares in the WCOW UVM. + NoDirectMap *bool `protobuf:"varint,2,opt,name=no_direct_map,json=noDirectMap,proto3,oneof" json:"no_direct_map,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WindowsBootOptions) Reset() { + *x = WindowsBootOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WindowsBootOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WindowsBootOptions) ProtoMessage() {} + +func (x *WindowsBootOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WindowsBootOptions.ProtoReflect.Descriptor instead. +func (*WindowsBootOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{10} +} + +func (x *WindowsBootOptions) GetDisableCompartmentNamespace() bool { + if x != nil && x.DisableCompartmentNamespace != nil { + return *x.DisableCompartmentNamespace + } + return false +} + +func (x *WindowsBootOptions) GetNoDirectMap() bool { + if x != nil && x.NoDirectMap != nil { + return *x.NoDirectMap + } + return false +} + +type WindowsGuestOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Do not inherit host timezone; default WCOW UVM time is UTC. + NoInheritHostTimezone *bool `protobuf:"varint,1,opt,name=no_inherit_host_timezone,json=noInheritHostTimezone,proto3,oneof" json:"no_inherit_host_timezone,omitempty"` + // Additional registry entries to apply in the guest. + AdditionalRegistryKeys []*RegistryValue `protobuf:"bytes,2,rep,name=additional_registry_keys,json=additionalRegistryKeys,proto3" json:"additional_registry_keys,omitempty"` + // Specifies whether to forward logs to the host or not. + ForwardLogs *bool `protobuf:"varint,3,opt,name=forward_logs,json=forwardLogs,proto3,oneof" json:"forward_logs,omitempty"` + // Specifies the log sources to be forwarded to the host. + LogSources *string `protobuf:"bytes,4,opt,name=log_sources,json=logSources,proto3,oneof" json:"log_sources,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WindowsGuestOptions) Reset() { + *x = WindowsGuestOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WindowsGuestOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WindowsGuestOptions) ProtoMessage() {} + +func (x *WindowsGuestOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WindowsGuestOptions.ProtoReflect.Descriptor instead. +func (*WindowsGuestOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{11} +} + +func (x *WindowsGuestOptions) GetNoInheritHostTimezone() bool { + if x != nil && x.NoInheritHostTimezone != nil { + return *x.NoInheritHostTimezone + } + return false +} + +func (x *WindowsGuestOptions) GetAdditionalRegistryKeys() []*RegistryValue { + if x != nil { + return x.AdditionalRegistryKeys + } + return nil +} + +func (x *WindowsGuestOptions) GetForwardLogs() bool { + if x != nil && x.ForwardLogs != nil { + return *x.ForwardLogs + } + return false +} + +func (x *WindowsGuestOptions) GetLogSources() string { + if x != nil && x.LogSources != nil { + return *x.LogSources + } + return "" +} + +type RegistryKey struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Target hive. + Hive RegistryHive `protobuf:"varint,1,opt,name=hive,proto3,enum=containerd.runhcs.sandbox.v1.RegistryHive" json:"hive,omitempty"` + // Key path. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Volatile key flag. + Volatile bool `protobuf:"varint,3,opt,name=volatile,proto3" json:"volatile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegistryKey) Reset() { + *x = RegistryKey{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegistryKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegistryKey) ProtoMessage() {} + +func (x *RegistryKey) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegistryKey.ProtoReflect.Descriptor instead. +func (*RegistryKey) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{12} +} + +func (x *RegistryKey) GetHive() RegistryHive { + if x != nil { + return x.Hive + } + return RegistryHive_REGISTRY_HIVE_SYSTEM +} + +func (x *RegistryKey) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RegistryKey) GetVolatile() bool { + if x != nil { + return x.Volatile + } + return false +} + +type RegistryValue struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Value location (hive + key path). + Key *RegistryKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Value name. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Value type. + Type RegistryValueType `protobuf:"varint,3,opt,name=type,proto3,enum=containerd.runhcs.sandbox.v1.RegistryValueType" json:"type,omitempty"` + // Typed payloads (one populated per type). + StringValue string `protobuf:"bytes,4,opt,name=string_value,json=stringValue,proto3" json:"string_value,omitempty"` + BinaryValue string `protobuf:"bytes,5,opt,name=binary_value,json=binaryValue,proto3" json:"binary_value,omitempty"` + DwordValue int32 `protobuf:"varint,6,opt,name=dword_value,json=dwordValue,proto3" json:"dword_value,omitempty"` + QwordValue int32 `protobuf:"varint,7,opt,name=qword_value,json=qwordValue,proto3" json:"qword_value,omitempty"` + CustomType int32 `protobuf:"varint,8,opt,name=custom_type,json=customType,proto3" json:"custom_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegistryValue) Reset() { + *x = RegistryValue{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegistryValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegistryValue) ProtoMessage() {} + +func (x *RegistryValue) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegistryValue.ProtoReflect.Descriptor instead. +func (*RegistryValue) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{13} +} + +func (x *RegistryValue) GetKey() *RegistryKey { + if x != nil { + return x.Key + } + return nil +} + +func (x *RegistryValue) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RegistryValue) GetType() RegistryValueType { + if x != nil { + return x.Type + } + return RegistryValueType_REGISTRY_VALUE_TYPE_NONE +} + +func (x *RegistryValue) GetStringValue() string { + if x != nil { + return x.StringValue + } + return "" +} + +func (x *RegistryValue) GetBinaryValue() string { + if x != nil { + return x.BinaryValue + } + return "" +} + +func (x *RegistryValue) GetDwordValue() int32 { + if x != nil { + return x.DwordValue + } + return 0 +} + +func (x *RegistryValue) GetQwordValue() int32 { + if x != nil { + return x.QwordValue + } + return 0 +} + +func (x *RegistryValue) GetCustomType() int32 { + if x != nil { + return x.CustomType + } + return 0 +} + +type LinuxHyperVOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Boot configuration for LCOW UVM. + LinuxBootOptions *LinuxBootOptions `protobuf:"bytes,1,opt,name=linuxBootOptions,proto3" json:"linuxBootOptions,omitempty"` + // Guest configuration for LCOW UVM. + LinuxGuestOptions *LinuxGuestOptions `protobuf:"bytes,2,opt,name=linuxGuestOptions,proto3" json:"linuxGuestOptions,omitempty"` + // Device configuration for LCOW UVM. + LinuxDeviceOptions *LinuxDeviceOptions `protobuf:"bytes,3,opt,name=linuxDeviceOptions,proto3" json:"linuxDeviceOptions,omitempty"` + // Confidential computing options for LCOW. + ConfidentialOptions *LCOWConfidentialOptions `protobuf:"bytes,4,opt,name=confidentialOptions,proto3" json:"confidentialOptions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LinuxHyperVOptions) Reset() { + *x = LinuxHyperVOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LinuxHyperVOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinuxHyperVOptions) ProtoMessage() {} + +func (x *LinuxHyperVOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LinuxHyperVOptions.ProtoReflect.Descriptor instead. +func (*LinuxHyperVOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{14} +} + +func (x *LinuxHyperVOptions) GetLinuxBootOptions() *LinuxBootOptions { + if x != nil { + return x.LinuxBootOptions + } + return nil +} + +func (x *LinuxHyperVOptions) GetLinuxGuestOptions() *LinuxGuestOptions { + if x != nil { + return x.LinuxGuestOptions + } + return nil +} + +func (x *LinuxHyperVOptions) GetLinuxDeviceOptions() *LinuxDeviceOptions { + if x != nil { + return x.LinuxDeviceOptions + } + return nil +} + +func (x *LinuxHyperVOptions) GetConfidentialOptions() *LCOWConfidentialOptions { + if x != nil { + return x.ConfidentialOptions + } + return nil +} + +type LinuxBootOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Root path for LCOW boot files. + BootFilesPath *string `protobuf:"bytes,1,opt,name=boot_files_path,json=bootFilesPath,proto3,oneof" json:"boot_files_path,omitempty"` + // Boot directly to kernel (skip UEFI). + KernelDirect *bool `protobuf:"varint,2,opt,name=kernel_direct,json=kernelDirect,proto3,oneof" json:"kernel_direct,omitempty"` + // Extra kernel cmdline options. + KernelBootOptions *string `protobuf:"bytes,3,opt,name=kernel_boot_options,json=kernelBootOptions,proto3,oneof" json:"kernel_boot_options,omitempty"` + // Preferred rootfs type selection (INITRD/VHD). + PreferredRootFsType *PreferredRootFSType `protobuf:"varint,4,opt,name=preferred_root_fs_type,json=preferredRootFsType,proto3,enum=containerd.runhcs.sandbox.v1.PreferredRootFSType,oneof" json:"preferred_root_fs_type,omitempty"` + // Enable cold discard hint for trimming non‑zeroed pages. + EnableColdDiscardHint *bool `protobuf:"varint,5,opt,name=enable_cold_discard_hint,json=enableColdDiscardHint,proto3,oneof" json:"enable_cold_discard_hint,omitempty"` + // Host Compatibility Layer toggle (presence-aware). + HclEnabled *bool `protobuf:"varint,6,opt,name=hcl_enabled,json=hclEnabled,proto3,oneof" json:"hcl_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LinuxBootOptions) Reset() { + *x = LinuxBootOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LinuxBootOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinuxBootOptions) ProtoMessage() {} + +func (x *LinuxBootOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LinuxBootOptions.ProtoReflect.Descriptor instead. +func (*LinuxBootOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{15} +} + +func (x *LinuxBootOptions) GetBootFilesPath() string { + if x != nil && x.BootFilesPath != nil { + return *x.BootFilesPath + } + return "" +} + +func (x *LinuxBootOptions) GetKernelDirect() bool { + if x != nil && x.KernelDirect != nil { + return *x.KernelDirect + } + return false +} + +func (x *LinuxBootOptions) GetKernelBootOptions() string { + if x != nil && x.KernelBootOptions != nil { + return *x.KernelBootOptions + } + return "" +} + +func (x *LinuxBootOptions) GetPreferredRootFsType() PreferredRootFSType { + if x != nil && x.PreferredRootFsType != nil { + return *x.PreferredRootFsType + } + return PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD +} + +func (x *LinuxBootOptions) GetEnableColdDiscardHint() bool { + if x != nil && x.EnableColdDiscardHint != nil { + return *x.EnableColdDiscardHint + } + return false +} + +func (x *LinuxBootOptions) GetHclEnabled() bool { + if x != nil && x.HclEnabled != nil { + return *x.HclEnabled + } + return false +} + +type LinuxGuestOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Disable LCOW time-sync service. + DisableTimeSyncService *bool `protobuf:"varint,1,opt,name=disable_time_sync_service,json=disableTimeSyncService,proto3,oneof" json:"disable_time_sync_service,omitempty"` + // Extra vsock ports to expose. + ExtraVsockPorts []uint32 `protobuf:"varint,2,rep,packed,name=extra_vsock_ports,json=extraVsockPorts,proto3" json:"extra_vsock_ports,omitempty"` + // Enable policy-based routing in guest. + PolicyBasedRouting *bool `protobuf:"varint,3,opt,name=policy_based_routing,json=policyBasedRouting,proto3,oneof" json:"policy_based_routing,omitempty"` + // Allow writable overlays for /var and /etc. + WritableOverlayDirs *bool `protobuf:"varint,4,opt,name=writable_overlay_dirs,json=writableOverlayDirs,proto3,oneof" json:"writable_overlay_dirs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LinuxGuestOptions) Reset() { + *x = LinuxGuestOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LinuxGuestOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinuxGuestOptions) ProtoMessage() {} + +func (x *LinuxGuestOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LinuxGuestOptions.ProtoReflect.Descriptor instead. +func (*LinuxGuestOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{16} +} + +func (x *LinuxGuestOptions) GetDisableTimeSyncService() bool { + if x != nil && x.DisableTimeSyncService != nil { + return *x.DisableTimeSyncService + } + return false +} + +func (x *LinuxGuestOptions) GetExtraVsockPorts() []uint32 { + if x != nil { + return x.ExtraVsockPorts + } + return nil +} + +func (x *LinuxGuestOptions) GetPolicyBasedRouting() bool { + if x != nil && x.PolicyBasedRouting != nil { + return *x.PolicyBasedRouting + } + return false +} + +func (x *LinuxGuestOptions) GetWritableOverlayDirs() bool { + if x != nil && x.WritableOverlayDirs != nil { + return *x.WritableOverlayDirs + } + return false +} + +type LinuxDeviceOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Max vPMem device count. + VpMemDeviceCount *uint32 `protobuf:"varint,1,opt,name=vp_mem_device_count,json=vpMemDeviceCount,proto3,oneof" json:"vp_mem_device_count,omitempty"` + // vPMem device size (bytes). + VpMemSizeBytes *uint64 `protobuf:"varint,2,opt,name=vp_mem_size_bytes,json=vpMemSizeBytes,proto3,oneof" json:"vp_mem_size_bytes,omitempty"` + // Disable LCOW vPMem layer multi-mapping. + VpMemNoMultiMapping *bool `protobuf:"varint,3,opt,name=vp_mem_no_multi_mapping,json=vpMemNoMultiMapping,proto3,oneof" json:"vp_mem_no_multi_mapping,omitempty"` + // Enable PCI support in LCOW kernel. + VpciEnabled *bool `protobuf:"varint,4,opt,name=vpci_enabled,json=vpciEnabled,proto3,oneof" json:"vpci_enabled,omitempty"` + // Assigned devices (e.g., SR-IOV). + AssignedDevices []*Device `protobuf:"bytes,5,rep,name=assigned_devices,json=assignedDevices,proto3" json:"assigned_devices,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LinuxDeviceOptions) Reset() { + *x = LinuxDeviceOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LinuxDeviceOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinuxDeviceOptions) ProtoMessage() {} + +func (x *LinuxDeviceOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LinuxDeviceOptions.ProtoReflect.Descriptor instead. +func (*LinuxDeviceOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{17} +} + +func (x *LinuxDeviceOptions) GetVpMemDeviceCount() uint32 { + if x != nil && x.VpMemDeviceCount != nil { + return *x.VpMemDeviceCount + } + return 0 +} + +func (x *LinuxDeviceOptions) GetVpMemSizeBytes() uint64 { + if x != nil && x.VpMemSizeBytes != nil { + return *x.VpMemSizeBytes + } + return 0 +} + +func (x *LinuxDeviceOptions) GetVpMemNoMultiMapping() bool { + if x != nil && x.VpMemNoMultiMapping != nil { + return *x.VpMemNoMultiMapping + } + return false +} + +func (x *LinuxDeviceOptions) GetVpciEnabled() bool { + if x != nil && x.VpciEnabled != nil { + return *x.VpciEnabled + } + return false +} + +func (x *LinuxDeviceOptions) GetAssignedDevices() []*Device { + if x != nil { + return x.AssignedDevices + } + return nil +} + +type Device struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Device identifier: interface class GUID, etc. + ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Device identifier type: "class", etc. + IdType string `protobuf:"bytes,2,opt,name=id_type,json=idType,proto3" json:"id_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Device) Reset() { + *x = Device{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Device) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Device) ProtoMessage() {} + +func (x *Device) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Device.ProtoReflect.Descriptor instead. +func (*Device) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{18} +} + +func (x *Device) GetID() string { + if x != nil { + return x.ID + } + return "" +} + +func (x *Device) GetIdType() string { + if x != nil { + return x.IdType + } + return "" +} + +type ConfidentialOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Guest state file (VMGS) path used by confidential UVM modes. + GuestStateFile *string `protobuf:"bytes,1,opt,name=guest_state_file,json=guestStateFile,proto3,oneof" json:"guest_state_file,omitempty"` + // Security policy to enforce inside the guest. + SecurityPolicy *string `protobuf:"bytes,2,opt,name=security_policy,json=securityPolicy,proto3,oneof" json:"security_policy,omitempty"` + // Security policy enforcer selection ("open-door", "standard", "rego"). + SecurityPolicyEnforcer *string `protobuf:"bytes,3,opt,name=security_policy_enforcer,json=securityPolicyEnforcer,proto3,oneof" json:"security_policy_enforcer,omitempty"` + // Signed UVM reference info file passed to guest. + UvmReferenceInfoFile *string `protobuf:"bytes,4,opt,name=uvm_reference_info_file,json=uvmReferenceInfoFile,proto3,oneof" json:"uvm_reference_info_file,omitempty"` + // no_security_hardware allows to do testing and development without requiring SNP hardware. + NoSecurityHardware *bool `protobuf:"varint,5,opt,name=no_security_hardware,json=noSecurityHardware,proto3,oneof" json:"no_security_hardware,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfidentialOptions) Reset() { + *x = ConfidentialOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfidentialOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfidentialOptions) ProtoMessage() {} + +func (x *ConfidentialOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfidentialOptions.ProtoReflect.Descriptor instead. +func (*ConfidentialOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{19} +} + +func (x *ConfidentialOptions) GetGuestStateFile() string { + if x != nil && x.GuestStateFile != nil { + return *x.GuestStateFile + } + return "" +} + +func (x *ConfidentialOptions) GetSecurityPolicy() string { + if x != nil && x.SecurityPolicy != nil { + return *x.SecurityPolicy + } + return "" +} + +func (x *ConfidentialOptions) GetSecurityPolicyEnforcer() string { + if x != nil && x.SecurityPolicyEnforcer != nil { + return *x.SecurityPolicyEnforcer + } + return "" +} + +func (x *ConfidentialOptions) GetUvmReferenceInfoFile() string { + if x != nil && x.UvmReferenceInfoFile != nil { + return *x.UvmReferenceInfoFile + } + return "" +} + +func (x *ConfidentialOptions) GetNoSecurityHardware() bool { + if x != nil && x.NoSecurityHardware != nil { + return *x.NoSecurityHardware + } + return false +} + +type LCOWConfidentialOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // LCOW common confidential options. + Options *ConfidentialOptions `protobuf:"bytes,1,opt,name=options,proto3" json:"options,omitempty"` + // Rootfs VHD path with dm-verity metadata (SNP mode). + DmVerityRootFsVhd *string `protobuf:"bytes,2,opt,name=dm_verity_root_fs_vhd,json=dmVerityRootFsVhd,proto3,oneof" json:"dm_verity_root_fs_vhd,omitempty"` + // Enable dm-verity presentation of rootfs (standalone SCSI attachment). + DmVerityMode *bool `protobuf:"varint,3,opt,name=dm_verity_mode,json=dmVerityMode,proto3,oneof" json:"dm_verity_mode,omitempty"` + // dm-mod.create parameters for rootfs integrity. + DmVerityCreateArgs *string `protobuf:"bytes,4,opt,name=dm_verity_create_args,json=dmVerityCreateArgs,proto3,oneof" json:"dm_verity_create_args,omitempty"` + // Encrypt LCOW scratch disks. + EnableScratchEncryption *bool `protobuf:"varint,5,opt,name=enable_scratch_encryption,json=enableScratchEncryption,proto3,oneof" json:"enable_scratch_encryption,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LCOWConfidentialOptions) Reset() { + *x = LCOWConfidentialOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LCOWConfidentialOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LCOWConfidentialOptions) ProtoMessage() {} + +func (x *LCOWConfidentialOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LCOWConfidentialOptions.ProtoReflect.Descriptor instead. +func (*LCOWConfidentialOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{20} +} + +func (x *LCOWConfidentialOptions) GetOptions() *ConfidentialOptions { + if x != nil { + return x.Options + } + return nil +} + +func (x *LCOWConfidentialOptions) GetDmVerityRootFsVhd() string { + if x != nil && x.DmVerityRootFsVhd != nil { + return *x.DmVerityRootFsVhd + } + return "" +} + +func (x *LCOWConfidentialOptions) GetDmVerityMode() bool { + if x != nil && x.DmVerityMode != nil { + return *x.DmVerityMode + } + return false +} + +func (x *LCOWConfidentialOptions) GetDmVerityCreateArgs() string { + if x != nil && x.DmVerityCreateArgs != nil { + return *x.DmVerityCreateArgs + } + return "" +} + +func (x *LCOWConfidentialOptions) GetEnableScratchEncryption() bool { + if x != nil && x.EnableScratchEncryption != nil { + return *x.EnableScratchEncryption + } + return false +} + +type WCOWConfidentialOptions struct { + state protoimpl.MessageState `protogen:"open.v1"` + // WCOW common confidential options. + Options *ConfidentialOptions `protobuf:"bytes,1,opt,name=options,proto3" json:"options,omitempty"` + // Disable secure boot (WCOW-only; testing/debugging). + DisableSecureBoot *bool `protobuf:"varint,2,opt,name=disable_secure_boot,json=disableSecureBoot,proto3,oneof" json:"disable_secure_boot,omitempty"` + // Attach EFI/boot VHD in writable mode (capture boot traces). + WritableEfi *bool `protobuf:"varint,3,opt,name=writable_efi,json=writableEfi,proto3,oneof" json:"writable_efi,omitempty"` + // allows overriding isolation type of a confidential pod. + IsolationType *string `protobuf:"bytes,4,opt,name=isolation_type,json=isolationType,proto3,oneof" json:"isolation_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WCOWConfidentialOptions) Reset() { + *x = WCOWConfidentialOptions{} + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WCOWConfidentialOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WCOWConfidentialOptions) ProtoMessage() {} + +func (x *WCOWConfidentialOptions) ProtoReflect() protoreflect.Message { + mi := &file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WCOWConfidentialOptions.ProtoReflect.Descriptor instead. +func (*WCOWConfidentialOptions) Descriptor() ([]byte, []int) { + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP(), []int{21} +} + +func (x *WCOWConfidentialOptions) GetOptions() *ConfidentialOptions { + if x != nil { + return x.Options + } + return nil +} + +func (x *WCOWConfidentialOptions) GetDisableSecureBoot() bool { + if x != nil && x.DisableSecureBoot != nil { + return *x.DisableSecureBoot + } + return false +} + +func (x *WCOWConfidentialOptions) GetWritableEfi() bool { + if x != nil && x.WritableEfi != nil { + return *x.WritableEfi + } + return false +} + +func (x *WCOWConfidentialOptions) GetIsolationType() string { + if x != nil && x.IsolationType != nil { + return *x.IsolationType + } + return "" +} + +var File_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto protoreflect.FileDescriptor + +const file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDesc = "" + + "\n" + + "Tgithub.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.proto\x12\x1ccontainerd.runhcs.sandbox.v1\"\xb9\x01\n" + + "\x05Specs\x12I\n" + + "\aprocess\x18\x01 \x01(\v2-.containerd.runhcs.sandbox.v1.ProcessIsolatedH\x00R\aprocess\x12R\n" + + "\n" + + "hypervisor\x18\x02 \x01(\v20.containerd.runhcs.sandbox.v1.HypervisorIsolatedH\x00R\n" + + "hypervisorB\x11\n" + + "\x0fisolation_level\"\x11\n" + + "\x0fProcessIsolated\"\xcd\x05\n" + + "\x12HypervisorIsolated\x12F\n" + + "\x04lcow\x18\x01 \x01(\v20.containerd.runhcs.sandbox.v1.LinuxHyperVOptionsH\x00R\x04lcow\x12H\n" + + "\x04wcow\x18\x02 \x01(\v22.containerd.runhcs.sandbox.v1.WindowsHyperVOptionsH\x00R\x04wcow\x12E\n" + + "\tcpuConfig\x18\x03 \x01(\v2'.containerd.runhcs.sandbox.v1.CPUConfigR\tcpuConfig\x12N\n" + + "\fmemoryConfig\x18\x04 \x01(\v2*.containerd.runhcs.sandbox.v1.MemoryConfigR\fmemoryConfig\x12Q\n" + + "\rstorageConfig\x18\x05 \x01(\v2+.containerd.runhcs.sandbox.v1.StorageConfigR\rstorageConfig\x12H\n" + + "\n" + + "numaConfig\x18\x06 \x01(\v2(.containerd.runhcs.sandbox.v1.NUMAConfigR\n" + + "numaConfig\x12Z\n" + + "\x10additionalConfig\x18\a \x01(\v2..containerd.runhcs.sandbox.v1.AdditionalConfigR\x10additionalConfig\x12%\n" + + "\fcpu_group_id\x18\b \x01(\tH\x01R\n" + + "cpuGroupId\x88\x01\x01\x127\n" + + "\x15resource_partition_id\x18\t \x01(\tH\x02R\x13resourcePartitionId\x88\x01\x01B\n" + + "\n" + + "\bplatformB\x0f\n" + + "\r_cpu_group_idB\x18\n" + + "\x16_resource_partition_id\"\x8e\x02\n" + + "\tCPUConfig\x12,\n" + + "\x0fprocessor_count\x18\x01 \x01(\x05H\x00R\x0eprocessorCount\x88\x01\x01\x12,\n" + + "\x0fprocessor_limit\x18\x02 \x01(\x05H\x01R\x0eprocessorLimit\x88\x01\x01\x12.\n" + + "\x10processor_weight\x18\x03 \x01(\x05H\x02R\x0fprocessorWeight\x88\x01\x01\x12'\n" + + "\farchitecture\x18\x04 \x01(\tH\x03R\farchitecture\x88\x01\x01B\x12\n" + + "\x10_processor_countB\x12\n" + + "\x10_processor_limitB\x13\n" + + "\x11_processor_weightB\x0f\n" + + "\r_architecture\"\xa9\x04\n" + + "\fMemoryConfig\x12.\n" + + "\x11memory_size_in_mb\x18\x01 \x01(\x04H\x00R\x0ememorySizeInMb\x88\x01\x01\x12/\n" + + "\x12low_mmio_gap_in_mb\x18\x02 \x01(\x04H\x01R\x0elowMmioGapInMb\x88\x01\x01\x123\n" + + "\x14high_mmio_base_in_mb\x18\x03 \x01(\x04H\x02R\x10highMmioBaseInMb\x88\x01\x01\x121\n" + + "\x13high_mmio_gap_in_mb\x18\x04 \x01(\x04H\x03R\x0fhighMmioGapInMb\x88\x01\x01\x12.\n" + + "\x10allow_overcommit\x18\x05 \x01(\bH\x04R\x0fallowOvercommit\x88\x01\x01\x12;\n" + + "\x17fully_physically_backed\x18\x06 \x01(\bH\x05R\x15fullyPhysicallyBacked\x88\x01\x01\x129\n" + + "\x16enable_deferred_commit\x18\a \x01(\bH\x06R\x14enableDeferredCommit\x88\x01\x01B\x14\n" + + "\x12_memory_size_in_mbB\x15\n" + + "\x13_low_mmio_gap_in_mbB\x17\n" + + "\x15_high_mmio_base_in_mbB\x16\n" + + "\x14_high_mmio_gap_in_mbB\x13\n" + + "\x11_allow_overcommitB\x1a\n" + + "\x18_fully_physically_backedB\x19\n" + + "\x17_enable_deferred_commit\"\xac\x02\n" + + "\rStorageConfig\x12<\n" + + "\x18storage_qos_iops_maximum\x18\x01 \x01(\x05H\x00R\x15storageQosIopsMaximum\x88\x01\x01\x12F\n" + + "\x1dstorage_qos_bandwidth_maximum\x18\x02 \x01(\x05H\x01R\x1astorageQosBandwidthMaximum\x88\x01\x01\x12:\n" + + "\x17no_writable_file_shares\x18\x03 \x01(\bH\x02R\x14noWritableFileShares\x88\x01\x01B\x1b\n" + + "\x19_storage_qos_iops_maximumB \n" + + "\x1e_storage_qos_bandwidth_maximumB\x1a\n" + + "\x18_no_writable_file_shares\"\xc9\x03\n" + + "\n" + + "NUMAConfig\x12D\n" + + "\x1dmax_memory_size_per_numa_node\x18\x01 \x01(\x04H\x00R\x18maxMemorySizePerNumaNode\x88\x01\x01\x12C\n" + + "\x1cmax_processors_per_numa_node\x18\x02 \x01(\rH\x01R\x18maxProcessorsPerNumaNode\x88\x01\x01\x12A\n" + + "\x1dpreferred_physical_numa_nodes\x18\x03 \x03(\rR\x1apreferredPhysicalNumaNodes\x12;\n" + + "\x1anuma_mapped_physical_nodes\x18\x04 \x03(\rR\x17numaMappedPhysicalNodes\x122\n" + + "\x15numa_processor_counts\x18\x05 \x03(\rR\x13numaProcessorCounts\x129\n" + + "\x19numa_memory_blocks_counts\x18\x06 \x03(\x04R\x16numaMemoryBlocksCountsB \n" + + "\x1e_max_memory_size_per_numa_nodeB\x1f\n" + + "\x1d_max_processors_per_numa_node\"\xc2\x04\n" + + "\x10AdditionalConfig\x125\n" + + "\x14network_config_proxy\x18\x01 \x01(\tH\x00R\x12networkConfigProxy\x88\x01\x01\x127\n" + + "\x15process_dump_location\x18\x02 \x01(\tH\x01R\x13processDumpLocation\x88\x01\x01\x123\n" + + "\x13dump_directory_path\x18\x03 \x01(\tH\x02R\x11dumpDirectoryPath\x88\x01\x01\x12\x84\x01\n" + + "\x18additional_hyperv_config\x18\x04 \x03(\v2J.containerd.runhcs.sandbox.v1.AdditionalConfig.AdditionalHypervConfigEntryR\x16additionalHypervConfig\x12&\n" + + "\fconsole_pipe\x18\x05 \x01(\tH\x03R\vconsolePipe\x88\x01\x01\x1a~\n" + + "\x1bAdditionalHypervConfigEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12I\n" + + "\x05value\x18\x02 \x01(\v23.containerd.runhcs.sandbox.v1.HvSocketServiceConfigR\x05value:\x028\x01B\x17\n" + + "\x15_network_config_proxyB\x18\n" + + "\x16_process_dump_locationB\x16\n" + + "\x14_dump_directory_pathB\x0f\n" + + "\r_console_pipe\"\xd6\x02\n" + + "\x15HvSocketServiceConfig\x12=\n" + + "\x18bind_security_descriptor\x18\x01 \x01(\tH\x00R\x16bindSecurityDescriptor\x88\x01\x01\x12C\n" + + "\x1bconnect_security_descriptor\x18\x02 \x01(\tH\x01R\x19connectSecurityDescriptor\x88\x01\x01\x125\n" + + "\x14allow_wildcard_binds\x18\x03 \x01(\bH\x02R\x12allowWildcardBinds\x88\x01\x01\x12\x1f\n" + + "\bdisabled\x18\x04 \x01(\bH\x03R\bdisabled\x88\x01\x01B\x1b\n" + + "\x19_bind_security_descriptorB\x1e\n" + + "\x1c_connect_security_descriptorB\x17\n" + + "\x15_allow_wildcard_bindsB\v\n" + + "\t_disabled\"\xc6\x02\n" + + "\x14WindowsHyperVOptions\x12`\n" + + "\x12windowsBootOptions\x18\x01 \x01(\v20.containerd.runhcs.sandbox.v1.WindowsBootOptionsR\x12windowsBootOptions\x12c\n" + + "\x13windowsGuestOptions\x18\x02 \x01(\v21.containerd.runhcs.sandbox.v1.WindowsGuestOptionsR\x13windowsGuestOptions\x12g\n" + + "\x13confidentialOptions\x18\x03 \x01(\v25.containerd.runhcs.sandbox.v1.WCOWConfidentialOptionsR\x13confidentialOptions\"\xba\x01\n" + + "\x12WindowsBootOptions\x12G\n" + + "\x1ddisable_compartment_namespace\x18\x01 \x01(\bH\x00R\x1bdisableCompartmentNamespace\x88\x01\x01\x12'\n" + + "\rno_direct_map\x18\x02 \x01(\bH\x01R\vnoDirectMap\x88\x01\x01B \n" + + "\x1e_disable_compartment_namespaceB\x10\n" + + "\x0e_no_direct_map\"\xc6\x02\n" + + "\x13WindowsGuestOptions\x12<\n" + + "\x18no_inherit_host_timezone\x18\x01 \x01(\bH\x00R\x15noInheritHostTimezone\x88\x01\x01\x12e\n" + + "\x18additional_registry_keys\x18\x02 \x03(\v2+.containerd.runhcs.sandbox.v1.RegistryValueR\x16additionalRegistryKeys\x12&\n" + + "\fforward_logs\x18\x03 \x01(\bH\x01R\vforwardLogs\x88\x01\x01\x12$\n" + + "\vlog_sources\x18\x04 \x01(\tH\x02R\n" + + "logSources\x88\x01\x01B\x1b\n" + + "\x19_no_inherit_host_timezoneB\x0f\n" + + "\r_forward_logsB\x0e\n" + + "\f_log_sources\"}\n" + + "\vRegistryKey\x12>\n" + + "\x04hive\x18\x01 \x01(\x0e2*.containerd.runhcs.sandbox.v1.RegistryHiveR\x04hive\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x1a\n" + + "\bvolatile\x18\x03 \x01(\bR\bvolatile\"\xce\x02\n" + + "\rRegistryValue\x12;\n" + + "\x03key\x18\x01 \x01(\v2).containerd.runhcs.sandbox.v1.RegistryKeyR\x03key\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12C\n" + + "\x04type\x18\x03 \x01(\x0e2/.containerd.runhcs.sandbox.v1.RegistryValueTypeR\x04type\x12!\n" + + "\fstring_value\x18\x04 \x01(\tR\vstringValue\x12!\n" + + "\fbinary_value\x18\x05 \x01(\tR\vbinaryValue\x12\x1f\n" + + "\vdword_value\x18\x06 \x01(\x05R\n" + + "dwordValue\x12\x1f\n" + + "\vqword_value\x18\a \x01(\x05R\n" + + "qwordValue\x12\x1f\n" + + "\vcustom_type\x18\b \x01(\x05R\n" + + "customType\"\x9a\x03\n" + + "\x12LinuxHyperVOptions\x12Z\n" + + "\x10linuxBootOptions\x18\x01 \x01(\v2..containerd.runhcs.sandbox.v1.LinuxBootOptionsR\x10linuxBootOptions\x12]\n" + + "\x11linuxGuestOptions\x18\x02 \x01(\v2/.containerd.runhcs.sandbox.v1.LinuxGuestOptionsR\x11linuxGuestOptions\x12`\n" + + "\x12linuxDeviceOptions\x18\x03 \x01(\v20.containerd.runhcs.sandbox.v1.LinuxDeviceOptionsR\x12linuxDeviceOptions\x12g\n" + + "\x13confidentialOptions\x18\x04 \x01(\v25.containerd.runhcs.sandbox.v1.LCOWConfidentialOptionsR\x13confidentialOptions\"\xf5\x03\n" + + "\x10LinuxBootOptions\x12+\n" + + "\x0fboot_files_path\x18\x01 \x01(\tH\x00R\rbootFilesPath\x88\x01\x01\x12(\n" + + "\rkernel_direct\x18\x02 \x01(\bH\x01R\fkernelDirect\x88\x01\x01\x123\n" + + "\x13kernel_boot_options\x18\x03 \x01(\tH\x02R\x11kernelBootOptions\x88\x01\x01\x12k\n" + + "\x16preferred_root_fs_type\x18\x04 \x01(\x0e21.containerd.runhcs.sandbox.v1.PreferredRootFSTypeH\x03R\x13preferredRootFsType\x88\x01\x01\x12<\n" + + "\x18enable_cold_discard_hint\x18\x05 \x01(\bH\x04R\x15enableColdDiscardHint\x88\x01\x01\x12$\n" + + "\vhcl_enabled\x18\x06 \x01(\bH\x05R\n" + + "hclEnabled\x88\x01\x01B\x12\n" + + "\x10_boot_files_pathB\x10\n" + + "\x0e_kernel_directB\x16\n" + + "\x14_kernel_boot_optionsB\x19\n" + + "\x17_preferred_root_fs_typeB\x1b\n" + + "\x19_enable_cold_discard_hintB\x0e\n" + + "\f_hcl_enabled\"\xc0\x02\n" + + "\x11LinuxGuestOptions\x12>\n" + + "\x19disable_time_sync_service\x18\x01 \x01(\bH\x00R\x16disableTimeSyncService\x88\x01\x01\x12*\n" + + "\x11extra_vsock_ports\x18\x02 \x03(\rR\x0fextraVsockPorts\x125\n" + + "\x14policy_based_routing\x18\x03 \x01(\bH\x01R\x12policyBasedRouting\x88\x01\x01\x127\n" + + "\x15writable_overlay_dirs\x18\x04 \x01(\bH\x02R\x13writableOverlayDirs\x88\x01\x01B\x1c\n" + + "\x1a_disable_time_sync_serviceB\x17\n" + + "\x15_policy_based_routingB\x18\n" + + "\x16_writable_overlay_dirs\"\x87\x03\n" + + "\x12LinuxDeviceOptions\x122\n" + + "\x13vp_mem_device_count\x18\x01 \x01(\rH\x00R\x10vpMemDeviceCount\x88\x01\x01\x12.\n" + + "\x11vp_mem_size_bytes\x18\x02 \x01(\x04H\x01R\x0evpMemSizeBytes\x88\x01\x01\x129\n" + + "\x17vp_mem_no_multi_mapping\x18\x03 \x01(\bH\x02R\x13vpMemNoMultiMapping\x88\x01\x01\x12&\n" + + "\fvpci_enabled\x18\x04 \x01(\bH\x03R\vvpciEnabled\x88\x01\x01\x12O\n" + + "\x10assigned_devices\x18\x05 \x03(\v2$.containerd.runhcs.sandbox.v1.DeviceR\x0fassignedDevicesB\x16\n" + + "\x14_vp_mem_device_countB\x14\n" + + "\x12_vp_mem_size_bytesB\x1a\n" + + "\x18_vp_mem_no_multi_mappingB\x0f\n" + + "\r_vpci_enabled\"1\n" + + "\x06Device\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" + + "\aid_type\x18\x02 \x01(\tR\x06idType\"\x9f\x03\n" + + "\x13ConfidentialOptions\x12-\n" + + "\x10guest_state_file\x18\x01 \x01(\tH\x00R\x0eguestStateFile\x88\x01\x01\x12,\n" + + "\x0fsecurity_policy\x18\x02 \x01(\tH\x01R\x0esecurityPolicy\x88\x01\x01\x12=\n" + + "\x18security_policy_enforcer\x18\x03 \x01(\tH\x02R\x16securityPolicyEnforcer\x88\x01\x01\x12:\n" + + "\x17uvm_reference_info_file\x18\x04 \x01(\tH\x03R\x14uvmReferenceInfoFile\x88\x01\x01\x125\n" + + "\x14no_security_hardware\x18\x05 \x01(\bH\x04R\x12noSecurityHardware\x88\x01\x01B\x13\n" + + "\x11_guest_state_fileB\x12\n" + + "\x10_security_policyB\x1b\n" + + "\x19_security_policy_enforcerB\x1a\n" + + "\x18_uvm_reference_info_fileB\x17\n" + + "\x15_no_security_hardware\"\xa6\x03\n" + + "\x17LCOWConfidentialOptions\x12K\n" + + "\aoptions\x18\x01 \x01(\v21.containerd.runhcs.sandbox.v1.ConfidentialOptionsR\aoptions\x125\n" + + "\x15dm_verity_root_fs_vhd\x18\x02 \x01(\tH\x00R\x11dmVerityRootFsVhd\x88\x01\x01\x12)\n" + + "\x0edm_verity_mode\x18\x03 \x01(\bH\x01R\fdmVerityMode\x88\x01\x01\x126\n" + + "\x15dm_verity_create_args\x18\x04 \x01(\tH\x02R\x12dmVerityCreateArgs\x88\x01\x01\x12?\n" + + "\x19enable_scratch_encryption\x18\x05 \x01(\bH\x03R\x17enableScratchEncryption\x88\x01\x01B\x18\n" + + "\x16_dm_verity_root_fs_vhdB\x11\n" + + "\x0f_dm_verity_modeB\x18\n" + + "\x16_dm_verity_create_argsB\x1c\n" + + "\x1a_enable_scratch_encryption\"\xab\x02\n" + + "\x17WCOWConfidentialOptions\x12K\n" + + "\aoptions\x18\x01 \x01(\v21.containerd.runhcs.sandbox.v1.ConfidentialOptionsR\aoptions\x123\n" + + "\x13disable_secure_boot\x18\x02 \x01(\bH\x00R\x11disableSecureBoot\x88\x01\x01\x12&\n" + + "\fwritable_efi\x18\x03 \x01(\bH\x01R\vwritableEfi\x88\x01\x01\x12*\n" + + "\x0eisolation_type\x18\x04 \x01(\tH\x02R\risolationType\x88\x01\x01B\x16\n" + + "\x14_disable_secure_bootB\x0f\n" + + "\r_writable_efiB\x11\n" + + "\x0f_isolation_type*w\n" + + "\fRegistryHive\x12\x18\n" + + "\x14REGISTRY_HIVE_SYSTEM\x10\x00\x12\x1a\n" + + "\x16REGISTRY_HIVE_SOFTWARE\x10\x01\x12\x1a\n" + + "\x16REGISTRY_HIVE_SECURITY\x10\x02\x12\x15\n" + + "\x11REGISTRY_HIVE_SAM\x10\x03*\xa5\x02\n" + + "\x11RegistryValueType\x12\x1c\n" + + "\x18REGISTRY_VALUE_TYPE_NONE\x10\x00\x12\x1e\n" + + "\x1aREGISTRY_VALUE_TYPE_STRING\x10\x01\x12'\n" + + "#REGISTRY_VALUE_TYPE_EXPANDED_STRING\x10\x02\x12$\n" + + " REGISTRY_VALUE_TYPE_MULTI_STRING\x10\x03\x12\x1e\n" + + "\x1aREGISTRY_VALUE_TYPE_BINARY\x10\x04\x12\x1e\n" + + "\x1aREGISTRY_VALUE_TYPE_D_WORD\x10\x05\x12\x1e\n" + + "\x1aREGISTRY_VALUE_TYPE_Q_WORD\x10\x06\x12#\n" + + "\x1fREGISTRY_VALUE_TYPE_CUSTOM_TYPE\x10\a*X\n" + + "\x13PreferredRootFSType\x12!\n" + + "\x1dPREFERRED_ROOT_FS_TYPE_INITRD\x10\x00\x12\x1e\n" + + "\x1aPREFERRED_ROOT_FS_TYPE_VHD\x10\x01BHZFgithub.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/sandboxspecb\x06proto3" + +var ( + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescOnce sync.Once + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescData []byte +) + +func file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescGZIP() []byte { + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescOnce.Do(func() { + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDesc), len(file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDesc))) + }) + return file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDescData +} + +var file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_goTypes = []any{ + (RegistryHive)(0), // 0: containerd.runhcs.sandbox.v1.RegistryHive + (RegistryValueType)(0), // 1: containerd.runhcs.sandbox.v1.RegistryValueType + (PreferredRootFSType)(0), // 2: containerd.runhcs.sandbox.v1.PreferredRootFSType + (*Specs)(nil), // 3: containerd.runhcs.sandbox.v1.Specs + (*ProcessIsolated)(nil), // 4: containerd.runhcs.sandbox.v1.ProcessIsolated + (*HypervisorIsolated)(nil), // 5: containerd.runhcs.sandbox.v1.HypervisorIsolated + (*CPUConfig)(nil), // 6: containerd.runhcs.sandbox.v1.CPUConfig + (*MemoryConfig)(nil), // 7: containerd.runhcs.sandbox.v1.MemoryConfig + (*StorageConfig)(nil), // 8: containerd.runhcs.sandbox.v1.StorageConfig + (*NUMAConfig)(nil), // 9: containerd.runhcs.sandbox.v1.NUMAConfig + (*AdditionalConfig)(nil), // 10: containerd.runhcs.sandbox.v1.AdditionalConfig + (*HvSocketServiceConfig)(nil), // 11: containerd.runhcs.sandbox.v1.HvSocketServiceConfig + (*WindowsHyperVOptions)(nil), // 12: containerd.runhcs.sandbox.v1.WindowsHyperVOptions + (*WindowsBootOptions)(nil), // 13: containerd.runhcs.sandbox.v1.WindowsBootOptions + (*WindowsGuestOptions)(nil), // 14: containerd.runhcs.sandbox.v1.WindowsGuestOptions + (*RegistryKey)(nil), // 15: containerd.runhcs.sandbox.v1.RegistryKey + (*RegistryValue)(nil), // 16: containerd.runhcs.sandbox.v1.RegistryValue + (*LinuxHyperVOptions)(nil), // 17: containerd.runhcs.sandbox.v1.LinuxHyperVOptions + (*LinuxBootOptions)(nil), // 18: containerd.runhcs.sandbox.v1.LinuxBootOptions + (*LinuxGuestOptions)(nil), // 19: containerd.runhcs.sandbox.v1.LinuxGuestOptions + (*LinuxDeviceOptions)(nil), // 20: containerd.runhcs.sandbox.v1.LinuxDeviceOptions + (*Device)(nil), // 21: containerd.runhcs.sandbox.v1.Device + (*ConfidentialOptions)(nil), // 22: containerd.runhcs.sandbox.v1.ConfidentialOptions + (*LCOWConfidentialOptions)(nil), // 23: containerd.runhcs.sandbox.v1.LCOWConfidentialOptions + (*WCOWConfidentialOptions)(nil), // 24: containerd.runhcs.sandbox.v1.WCOWConfidentialOptions + nil, // 25: containerd.runhcs.sandbox.v1.AdditionalConfig.AdditionalHypervConfigEntry +} +var file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_depIdxs = []int32{ + 4, // 0: containerd.runhcs.sandbox.v1.Specs.process:type_name -> containerd.runhcs.sandbox.v1.ProcessIsolated + 5, // 1: containerd.runhcs.sandbox.v1.Specs.hypervisor:type_name -> containerd.runhcs.sandbox.v1.HypervisorIsolated + 17, // 2: containerd.runhcs.sandbox.v1.HypervisorIsolated.lcow:type_name -> containerd.runhcs.sandbox.v1.LinuxHyperVOptions + 12, // 3: containerd.runhcs.sandbox.v1.HypervisorIsolated.wcow:type_name -> containerd.runhcs.sandbox.v1.WindowsHyperVOptions + 6, // 4: containerd.runhcs.sandbox.v1.HypervisorIsolated.cpuConfig:type_name -> containerd.runhcs.sandbox.v1.CPUConfig + 7, // 5: containerd.runhcs.sandbox.v1.HypervisorIsolated.memoryConfig:type_name -> containerd.runhcs.sandbox.v1.MemoryConfig + 8, // 6: containerd.runhcs.sandbox.v1.HypervisorIsolated.storageConfig:type_name -> containerd.runhcs.sandbox.v1.StorageConfig + 9, // 7: containerd.runhcs.sandbox.v1.HypervisorIsolated.numaConfig:type_name -> containerd.runhcs.sandbox.v1.NUMAConfig + 10, // 8: containerd.runhcs.sandbox.v1.HypervisorIsolated.additionalConfig:type_name -> containerd.runhcs.sandbox.v1.AdditionalConfig + 25, // 9: containerd.runhcs.sandbox.v1.AdditionalConfig.additional_hyperv_config:type_name -> containerd.runhcs.sandbox.v1.AdditionalConfig.AdditionalHypervConfigEntry + 13, // 10: containerd.runhcs.sandbox.v1.WindowsHyperVOptions.windowsBootOptions:type_name -> containerd.runhcs.sandbox.v1.WindowsBootOptions + 14, // 11: containerd.runhcs.sandbox.v1.WindowsHyperVOptions.windowsGuestOptions:type_name -> containerd.runhcs.sandbox.v1.WindowsGuestOptions + 24, // 12: containerd.runhcs.sandbox.v1.WindowsHyperVOptions.confidentialOptions:type_name -> containerd.runhcs.sandbox.v1.WCOWConfidentialOptions + 16, // 13: containerd.runhcs.sandbox.v1.WindowsGuestOptions.additional_registry_keys:type_name -> containerd.runhcs.sandbox.v1.RegistryValue + 0, // 14: containerd.runhcs.sandbox.v1.RegistryKey.hive:type_name -> containerd.runhcs.sandbox.v1.RegistryHive + 15, // 15: containerd.runhcs.sandbox.v1.RegistryValue.key:type_name -> containerd.runhcs.sandbox.v1.RegistryKey + 1, // 16: containerd.runhcs.sandbox.v1.RegistryValue.type:type_name -> containerd.runhcs.sandbox.v1.RegistryValueType + 18, // 17: containerd.runhcs.sandbox.v1.LinuxHyperVOptions.linuxBootOptions:type_name -> containerd.runhcs.sandbox.v1.LinuxBootOptions + 19, // 18: containerd.runhcs.sandbox.v1.LinuxHyperVOptions.linuxGuestOptions:type_name -> containerd.runhcs.sandbox.v1.LinuxGuestOptions + 20, // 19: containerd.runhcs.sandbox.v1.LinuxHyperVOptions.linuxDeviceOptions:type_name -> containerd.runhcs.sandbox.v1.LinuxDeviceOptions + 23, // 20: containerd.runhcs.sandbox.v1.LinuxHyperVOptions.confidentialOptions:type_name -> containerd.runhcs.sandbox.v1.LCOWConfidentialOptions + 2, // 21: containerd.runhcs.sandbox.v1.LinuxBootOptions.preferred_root_fs_type:type_name -> containerd.runhcs.sandbox.v1.PreferredRootFSType + 21, // 22: containerd.runhcs.sandbox.v1.LinuxDeviceOptions.assigned_devices:type_name -> containerd.runhcs.sandbox.v1.Device + 22, // 23: containerd.runhcs.sandbox.v1.LCOWConfidentialOptions.options:type_name -> containerd.runhcs.sandbox.v1.ConfidentialOptions + 22, // 24: containerd.runhcs.sandbox.v1.WCOWConfidentialOptions.options:type_name -> containerd.runhcs.sandbox.v1.ConfidentialOptions + 11, // 25: containerd.runhcs.sandbox.v1.AdditionalConfig.AdditionalHypervConfigEntry.value:type_name -> containerd.runhcs.sandbox.v1.HvSocketServiceConfig + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name +} + +func init() { + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_init() +} +func file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_init() { + if File_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto != nil { + return + } + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[0].OneofWrappers = []any{ + (*Specs_Process)(nil), + (*Specs_Hypervisor)(nil), + } + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[2].OneofWrappers = []any{ + (*HypervisorIsolated_Lcow)(nil), + (*HypervisorIsolated_Wcow)(nil), + } + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[3].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[4].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[5].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[6].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[7].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[8].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[10].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[11].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[15].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[16].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[17].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[19].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[20].OneofWrappers = []any{} + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes[21].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDesc), len(file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_rawDesc)), + NumEnums: 3, + NumMessages: 23, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_goTypes, + DependencyIndexes: file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_depIdxs, + EnumInfos: file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_enumTypes, + MessageInfos: file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_msgTypes, + }.Build() + File_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto = out.File + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_goTypes = nil + file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_sandboxspec_sandbox_proto_depIdxs = nil +} diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.proto b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.proto new file mode 100644 index 0000000000..4302e41514 --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox.proto @@ -0,0 +1,439 @@ +syntax = "proto3"; + +package containerd.runhcs.sandbox.v1; + +option go_package = "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/sandboxspec"; + +// ---------------------------------------------------------------------------- +// High-level proto structure for sandbox options +// These options are used to define a sandbox for all types of pods. +// ---------------------------------------------------------------------------- +// +// Specs +// ├─ isolation_level (oneof) +// │ ├─ ProcessIsolated +// │ └─ HypervisorIsolated +// │ ├─ platform (oneof) +// │ │ ├─ LinuxHyperVOptions +// │ │ └─ WindowsHyperVOptions +// │ ├─ CPUConfig +// │ ├─ MemoryConfig +// │ ├─ StorageConfig +// │ ├─ NUMAConfig +// │ └─ AdditionalConfig +// │ └─ cpu_group_id +// │ └─ resource_partition_id +// +// LinuxHyperVOptions +// ├─ LinuxBootOptions +// ├─ LinuxGuestOptions +// ├─ LinuxDeviceOptions +// └─ LCOWConfidentialOptions +// +// WindowsHyperVOptions +// ├─ WindowsBootOptions +// ├─ WindowsGuestOptions +// └─ WCOWConfidentialOptions +// +// AdditionalConfig +// └─ HvSocketServiceConfig (map) +// +// Confidential options +// ├─ LCOWConfidentialOptions → ConfidentialOptions +// └─ WCOWConfidentialOptions → ConfidentialOptions +// + +// ---------------------------------------------------------------------------- +// Top-level Sandbox specification +// ---------------------------------------------------------------------------- + +message Specs { + // Sandbox isolation mode. + oneof isolation_level { + // Process-isolated sandbox (no UVM). + ProcessIsolated process = 1; + // Hypervisor-isolated sandbox (UVM-backed). + HypervisorIsolated hypervisor = 2; + } +} + +// ---------------------------------------------------------------------------- +// Process-isolated sandbox +// ---------------------------------------------------------------------------- + +message ProcessIsolated { + // No options for process isolation as of now; +} + +// ---------------------------------------------------------------------------- +// Hypervisor-isolated sandbox (UVM-backed) +// ---------------------------------------------------------------------------- + +message HypervisorIsolated { + // Platform-specific UVM options. + oneof platform { + // Linux UVM options. + LinuxHyperVOptions lcow = 1; + // Windows UVM options. + WindowsHyperVOptions wcow = 2; + } + + // UVM CPU topology. + CPUConfig cpuConfig = 3; + + // UVM memory sizing and commit policy; MMIO aperture tuning. + MemoryConfig memoryConfig = 4; + + // UVM storage QoS caps and file-share hardening. + StorageConfig storageConfig = 5; + + // UVM vNUMA hints (implicit/explicit topology). + NUMAConfig numaConfig = 6; + + // Misc sandbox controls: networking proxy, dump paths, HvSocket services, console pipe. + AdditionalConfig additionalConfig = 7; + + // Assign the UVM to a CPU group. Mutually exclusive with resource_partition_id. + optional string cpu_group_id = 8; + + // Resource partition GUID to associate the UVM with (has its own CPU group). + // Mutually exclusive with cpu_group_id. + optional string resource_partition_id = 9; +} + +// ---------------------------------------------------------------------------- +// CPU configuration +// ---------------------------------------------------------------------------- + +message CPUConfig { + // vCPU count override for the UVM. On UVM, count/limit/weight may be combined. + optional int32 processor_count = 1; + + // vCPU percentage cap: 1..100000 (100000 = 100%). Omitted => platform default. + optional int32 processor_limit = 2; + + // vCPU scheduling weight: 0..10000 (100 default). Omitted => default. + optional int32 processor_weight = 3; + + // architecture represents the architecture of the platform. + optional string architecture = 4; +} + +// ---------------------------------------------------------------------------- +// Memory configuration +// ---------------------------------------------------------------------------- + +message MemoryConfig { + // Total UVM memory size in MB (MB units; OCI uses bytes). + optional uint64 memory_size_in_mb = 1; + + // MMIO aperture tuning (low gap/base/high gap in MB). + optional uint64 low_mmio_gap_in_mb = 2; + optional uint64 high_mmio_base_in_mb = 3; + optional uint64 high_mmio_gap_in_mb = 4; + + // Allow virtual memory overcommit (true by default). Set false for fully physical backing. + optional bool allow_overcommit = 5; + + // Enforce fully physically backed memory, including future device additions. + optional bool fully_physically_backed = 6; + + // Enable deferred commit for virtual memory (defaults to false). + optional bool enable_deferred_commit = 7; +} + +// ---------------------------------------------------------------------------- +// Storage configuration +// ---------------------------------------------------------------------------- + +message StorageConfig { + // Max storage IOPS; 0/omitted => platform default. + optional int32 storage_qos_iops_maximum = 1; + + // Max storage bandwidth in bytes/sec; 0/omitted => platform default. + optional int32 storage_qos_bandwidth_maximum = 2; + + // Disallow any writable file shares (e.g., VSMB/Plan9) to the UVM. + optional bool no_writable_file_shares = 3; +} + +// ---------------------------------------------------------------------------- +// NUMA configuration +// ---------------------------------------------------------------------------- + +message NUMAConfig { + // Implicit vNUMA: max memory per node (MB). + optional uint64 max_memory_size_per_numa_node = 1; + + // Implicit vNUMA: max processors per node. + optional uint32 max_processors_per_numa_node = 2; + + // Implicit vNUMA: preferred physical NUMA nodes. + repeated uint32 preferred_physical_numa_nodes = 3; + + // Explicit vNUMA: pNUMA -> vNUMA mapping by index. + repeated uint32 numa_mapped_physical_nodes = 4; + + // Explicit vNUMA: processor counts per vNUMA index. + repeated uint32 numa_processor_counts = 5; + + // Explicit vNUMA: memory block counts per vNUMA index. + repeated uint64 numa_memory_blocks_counts = 6; +} + +// ---------------------------------------------------------------------------- +// Additional sandbox controls +// ---------------------------------------------------------------------------- + +message AdditionalConfig { + // ncproxy service address for network setup; when set, use ncproxy. + optional string network_config_proxy = 1; + + // In-guest path for container process dumps; prefer a mounted volume over scratch. + optional string process_dump_location = 2; + + // Host directory to collect UVM crash dumps. + optional string dump_directory_path = 3; + + // HvSocket per-service configuration (bind/connect SDDL, wildcard, disabled). + map additional_hyperv_config = 4; + + // Serial console named pipe (e.g., \\.\pipe\) for the UVM console. + optional string console_pipe = 5; +} + +message HvSocketServiceConfig { + // Host bind permission SDDL. + optional string bind_security_descriptor = 1; + + // Host connect permission SDDL. + optional string connect_security_descriptor = 2; + + // Allow wildcard binds per policy. + optional bool allow_wildcard_binds = 3; + + // Disable service (refuse new, cancel existing connections). + optional bool disabled = 4; +} + +// ---------------------------------------------------------------------------- +// Windows Hyper-V (WCOW) configuration +// ---------------------------------------------------------------------------- + +message WindowsHyperVOptions { + // Boot configuration for WCOW UVM. + WindowsBootOptions windowsBootOptions = 1; + + // Guest configuration for WCOW UVM. + WindowsGuestOptions windowsGuestOptions = 2; + + // Confidential computing options for WCOW. + WCOWConfidentialOptions confidentialOptions = 3; +} + +message WindowsBootOptions { + // Disable network compartment namespacing in the WCOW UVM. + optional bool disable_compartment_namespace = 1; + + // Disable direct mapping for VSMB shares in the WCOW UVM. + optional bool no_direct_map = 2; +} + +message WindowsGuestOptions { + // Do not inherit host timezone; default WCOW UVM time is UTC. + optional bool no_inherit_host_timezone = 1; + + // Additional registry entries to apply in the guest. + repeated RegistryValue additional_registry_keys = 2; + + // Specifies whether to forward logs to the host or not. + optional bool forward_logs = 3; + + // Specifies the log sources to be forwarded to the host. + optional string log_sources = 4; +} + +// ---------------------------------------------------------------------------- +// Registry +// ---------------------------------------------------------------------------- + +enum RegistryHive { + REGISTRY_HIVE_SYSTEM = 0; + REGISTRY_HIVE_SOFTWARE = 1; + REGISTRY_HIVE_SECURITY = 2; + REGISTRY_HIVE_SAM = 3; +} + +message RegistryKey { + // Target hive. + RegistryHive hive = 1; + + // Key path. + string name = 2; + + // Volatile key flag. + bool volatile = 3; +} + +enum RegistryValueType { + REGISTRY_VALUE_TYPE_NONE = 0; + REGISTRY_VALUE_TYPE_STRING = 1; + REGISTRY_VALUE_TYPE_EXPANDED_STRING = 2; + REGISTRY_VALUE_TYPE_MULTI_STRING = 3; + REGISTRY_VALUE_TYPE_BINARY = 4; + REGISTRY_VALUE_TYPE_D_WORD = 5; + REGISTRY_VALUE_TYPE_Q_WORD = 6; + REGISTRY_VALUE_TYPE_CUSTOM_TYPE = 7; +} + +message RegistryValue { + // Value location (hive + key path). + RegistryKey key = 1; + + // Value name. + string name = 2; + + // Value type. + RegistryValueType type = 3; + + // Typed payloads (one populated per type). + string string_value = 4; + string binary_value = 5; + int32 dword_value = 6; + int32 qword_value = 7; + int32 custom_type = 8; +} + +// ---------------------------------------------------------------------------- +// Linux Hyper-V (LCOW) configuration +// ---------------------------------------------------------------------------- + +message LinuxHyperVOptions { + // Boot configuration for LCOW UVM. + LinuxBootOptions linuxBootOptions = 1; + + // Guest configuration for LCOW UVM. + LinuxGuestOptions linuxGuestOptions = 2; + + // Device configuration for LCOW UVM. + LinuxDeviceOptions linuxDeviceOptions = 3; + + // Confidential computing options for LCOW. + LCOWConfidentialOptions confidentialOptions = 4; +} + +message LinuxBootOptions { + // Root path for LCOW boot files. + optional string boot_files_path = 1; + + // Boot directly to kernel (skip UEFI). + optional bool kernel_direct = 2; + + // Extra kernel cmdline options. + optional string kernel_boot_options = 3; + + // Preferred rootfs type selection (INITRD/VHD). + optional PreferredRootFSType preferred_root_fs_type = 4; + + // Enable cold discard hint for trimming non‑zeroed pages. + optional bool enable_cold_discard_hint = 5; + + // Host Compatibility Layer toggle (presence-aware). + optional bool hcl_enabled = 6; +} + +message LinuxGuestOptions { + // Disable LCOW time-sync service. + optional bool disable_time_sync_service = 1; + + // Extra vsock ports to expose. + repeated uint32 extra_vsock_ports = 2; + + // Enable policy-based routing in guest. + optional bool policy_based_routing = 3; + + // Allow writable overlays for /var and /etc. + optional bool writable_overlay_dirs = 4; +} + +message LinuxDeviceOptions { + // Max vPMem device count. + optional uint32 vp_mem_device_count = 1; + + // vPMem device size (bytes). + optional uint64 vp_mem_size_bytes = 2; + + // Disable LCOW vPMem layer multi-mapping. + optional bool vp_mem_no_multi_mapping = 3; + + // Enable PCI support in LCOW kernel. + optional bool vpci_enabled = 4; + + // Assigned devices (e.g., SR-IOV). + repeated Device assigned_devices = 5; +} + +enum PreferredRootFSType { + PREFERRED_ROOT_FS_TYPE_INITRD = 0; + PREFERRED_ROOT_FS_TYPE_VHD = 1; +} + +message Device { + // Device identifier: interface class GUID, etc. + string id = 1; + + // Device identifier type: "class", etc. + string id_type = 2; +} + +// ---------------------------------------------------------------------------- +// Confidential computing options +// ---------------------------------------------------------------------------- + +message ConfidentialOptions { + // Guest state file (VMGS) path used by confidential UVM modes. + optional string guest_state_file = 1; + + // Security policy to enforce inside the guest. + optional string security_policy = 2; + + // Security policy enforcer selection ("open-door", "standard", "rego"). + optional string security_policy_enforcer = 3; + + // Signed UVM reference info file passed to guest. + optional string uvm_reference_info_file = 4; + + // no_security_hardware allows to do testing and development without requiring SNP hardware. + optional bool no_security_hardware = 5; +} + +message LCOWConfidentialOptions { + // LCOW common confidential options. + ConfidentialOptions options = 1; + + // Rootfs VHD path with dm-verity metadata (SNP mode). + optional string dm_verity_root_fs_vhd = 2; + + // Enable dm-verity presentation of rootfs (standalone SCSI attachment). + optional bool dm_verity_mode = 3; + + // dm-mod.create parameters for rootfs integrity. + optional string dm_verity_create_args = 4; + + // Encrypt LCOW scratch disks. + optional bool enable_scratch_encryption = 5; +} + +message WCOWConfidentialOptions { + // WCOW common confidential options. + ConfidentialOptions options = 1; + + // Disable secure boot (WCOW-only; testing/debugging). + optional bool disable_secure_boot = 2; + + // Attach EFI/boot VHD in writable mode (capture boot traces). + optional bool writable_efi = 3; + + // allows overriding isolation type of a confidential pod. + optional string isolation_type = 4; +} diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs.go new file mode 100644 index 0000000000..b5d6b3c23c --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs.go @@ -0,0 +1,689 @@ +package sandboxspec + +import ( + "context" + "fmt" + "strings" + + runhcsoptions "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" + iannotations "github.com/Microsoft/hcsshim/internal/annotations" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/oci" + shimannotations "github.com/Microsoft/hcsshim/pkg/annotations" + + "github.com/opencontainers/runtime-spec/specs-go" +) + +// Generate generates Specs based on provided options and annotations. +// These specifications define the configuration for the sandbox environment. +func Generate( + opts *runhcsoptions.Options, + annotations map[string]string, + devices []specs.WindowsDevice, +) (*Specs, error) { + if opts == nil { + return nil, fmt.Errorf("no runhcs options provided") + } + + // Decide Isolation based on options: PROCESS vs HYPERVISOR + switch opts.SandboxIsolation { + case runhcsoptions.Options_PROCESS: + // Windows process isolation -> no UVM + return &Specs{ + IsolationLevel: &Specs_Process{ + Process: &ProcessIsolated{}, + }, + }, nil + + case runhcsoptions.Options_HYPERVISOR: + ctx := context.Background() + // UVM-backed isolation + osName, arch, err := splitPlatform(opts.SandboxPlatform) + if err != nil { + return nil, fmt.Errorf("failed to parse platform: %w", err) + } + + // Process annotations prior to parsing them into Specs. + err = processAnnotations(ctx, opts, annotations) + if err != nil { + return nil, fmt.Errorf("failed to process annotations: %w", err) + } + + // Create HypervisorIsolated spec + hyper := &HypervisorIsolated{} + + // CPU Configuration + cpuConfig, err := parseCPUParameters(ctx, opts, annotations, arch) + if err != nil { + return nil, fmt.Errorf("failed to parse CPU parameters: %w", err) + } + + hyper.CpuConfig = cpuConfig + + // Memory Configuration + memoryConfig, err := parseMemoryParameters(ctx, opts, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Memory parameters: %w", err) + } + + hyper.MemoryConfig = memoryConfig + + // Storage Configuration + storageConfig, err := parseStorageParameters(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Storage parameters: %w", err) + } + + hyper.StorageConfig = storageConfig + + // NUMA Configuration + numaConfig, err := parseNUMAParameters(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse NUMA parameters: %w", err) + } + + hyper.NumaConfig = numaConfig + + // Additional Configurations + additionalConfig, err := parseAdditionalConfigurations(ctx, opts, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Additional parameters: %w", err) + } + + hyper.AdditionalConfig = additionalConfig + + // CPU group configuration + cpuGroupID := oci.ParseAnnotationsString(annotations, shimannotations.CPUGroupID, "") + if cpuGroupID != "" { + hyper.CpuGroupID = &cpuGroupID + } + + // Resource Partition ID + resourcePartitionID := oci.ParseAnnotationsString(annotations, shimannotations.ResourcePartitionID, "") + if resourcePartitionID != "" { + hyper.ResourcePartitionID = &resourcePartitionID + } + + switch osName { + case "linux": + // LCOW platform-specific options + lcow := &LinuxHyperVOptions{} + + // Linux Boot Options + bootOptions, err := parseLinuxBootOptions(ctx, opts, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Linux boot options: %w", err) + } + + lcow.LinuxBootOptions = bootOptions + + guestOptions, err := parseLinuxGuestOptions(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Linux guest options: %w", err) + } + + lcow.LinuxGuestOptions = guestOptions + + deviceOptions, err := parseLinuxDeviceOptions(ctx, annotations, devices) + if err != nil { + return nil, fmt.Errorf("failed to parse Linux device options: %w", err) + } + + lcow.LinuxDeviceOptions = deviceOptions + + confidentialOptions, err := parseLinuxConfidentialOptions(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Linux confidential options: %w", err) + } + + lcow.ConfidentialOptions = confidentialOptions + + hyper.Platform = &HypervisorIsolated_Lcow{lcow} + + case "windows": + // WCOW platform-specific options + wcow := &WindowsHyperVOptions{} + + bootOptions, err := parseWindowsBootOptions(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Windows boot options: %w", err) + } + + wcow.WindowsBootOptions = bootOptions + + guestOptions, err := parseWindowsGuestOptions(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Windows guest options: %w", err) + } + + wcow.WindowsGuestOptions = guestOptions + + confidentialOptions, err := parseWindowsConfidentialOptions(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse Windows confidential options: %w", err) + } + + wcow.ConfidentialOptions = confidentialOptions + + hyper.Platform = &HypervisorIsolated_Wcow{wcow} + + default: + return nil, fmt.Errorf("unsupported sandbox platform os: %s", osName) + } + + return &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: hyper, + }, + }, nil + + default: + return nil, fmt.Errorf("unsupported sandbox_isolation: %v", opts.SandboxIsolation) + } +} + +// processAnnotations applies default annotations and processes them. +func processAnnotations(ctx context.Context, opts *runhcsoptions.Options, annotations map[string]string) error { + // Apply default annotations. + for key, value := range opts.DefaultContainerAnnotations { + // Only set default if not already set in annotations + if _, exists := annotations[key]; !exists { + annotations[key] = value + } + } + + err := oci.ProcessAnnotations(ctx, annotations) + if err != nil { + return err + } + + return nil +} + +// parseCPUParameters parses CPU related parameters from annotations and options. +func parseCPUParameters(ctx context.Context, opts *runhcsoptions.Options, annotations map[string]string, arch string) (*CPUConfig, error) { + cpu := &CPUConfig{} + + if _, ok := annotations[shimannotations.ProcessorCount]; ok { + cpuCount := oci.ParseAnnotationsInt32(ctx, annotations, shimannotations.ProcessorCount, 0) + if cpuCount != 0 { + cpu.ProcessorCount = &cpuCount + } + } else if opts.VmProcessorCount != 0 { + cpu.ProcessorCount = &opts.VmProcessorCount + } + + cpuLimit := oci.ParseAnnotationsInt32(ctx, annotations, shimannotations.ProcessorLimit, 0) + if cpuLimit != 0 { + cpu.ProcessorLimit = &cpuLimit + } + + cpuWeight := oci.ParseAnnotationsInt32(ctx, annotations, shimannotations.ProcessorWeight, 0) + if cpuWeight != 0 { + cpu.ProcessorWeight = &cpuWeight + } + + if arch != "" { + cpu.Architecture = &arch + } + + return cpu, nil +} + +// parseMemoryParameters parses memory related parameters from annotations and options. +func parseMemoryParameters(ctx context.Context, opts *runhcsoptions.Options, annotations map[string]string) (*MemoryConfig, error) { + mem := &MemoryConfig{} + + if _, ok := annotations[shimannotations.MemorySizeInMB]; ok { + memorySizeMB := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.MemorySizeInMB, 0) + if memorySizeMB != 0 { + mem.MemorySizeInMb = &memorySizeMB + } + } else if opts.VmMemorySizeInMb != 0 { + memorySizeMB := uint64(opts.VmMemorySizeInMb) + mem.MemorySizeInMb = &memorySizeMB + } + + lowMMIOGapInMB := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.MemoryLowMMIOGapInMB, 0) + if lowMMIOGapInMB != 0 { + mem.LowMmioGapInMb = &lowMMIOGapInMB + } + + highMMIOBaseInMB := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.MemoryHighMMIOBaseInMB, 0) + if highMMIOBaseInMB != 0 { + mem.HighMmioBaseInMb = &highMMIOBaseInMB + } + + highMMIOGapInMB := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.MemoryHighMMIOGapInMB, 0) + if highMMIOGapInMB != 0 { + mem.HighMmioGapInMb = &highMMIOGapInMB + } + + allowOvercommit := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.AllowOvercommit) + mem.AllowOvercommit = allowOvercommit + + enableDeferredCommit := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.EnableDeferredCommit) + mem.EnableDeferredCommit = enableDeferredCommit + + fullyPhysicallyBacked := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.FullyPhysicallyBacked) + mem.FullyPhysicallyBacked = fullyPhysicallyBacked + + return mem, nil +} + +// parseStorageParameters parses storage related parameters from annotations and options. +func parseStorageParameters(ctx context.Context, annotations map[string]string) (*StorageConfig, error) { + storage := &StorageConfig{} + + noWritableFileShares := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.DisableWritableFileShares) + storage.NoWritableFileShares = noWritableFileShares + + storageQosBandwidthMaximum := oci.ParseAnnotationsInt32(ctx, annotations, shimannotations.StorageQoSBandwidthMaximum, 0) + if storageQosBandwidthMaximum != 0 { + storage.StorageQosBandwidthMaximum = &storageQosBandwidthMaximum + } + + storageQosIopsMaximum := oci.ParseAnnotationsInt32(ctx, annotations, shimannotations.StorageQoSIopsMaximum, 0) + if storageQosIopsMaximum != 0 { + storage.StorageQosIopsMaximum = &storageQosIopsMaximum + } + + return storage, nil +} + +// parseNUMAParameters parses NUMA related parameters from annotations. +func parseNUMAParameters(ctx context.Context, annotations map[string]string) (*NUMAConfig, error) { + numa := &NUMAConfig{} + + maxProcessorsPerNumaNode := oci.ParseAnnotationsUint32(ctx, annotations, shimannotations.NumaMaximumProcessorsPerNode, 0) + if maxProcessorsPerNumaNode != 0 { + numa.MaxProcessorsPerNumaNode = &maxProcessorsPerNumaNode + } + + maxMemorySizePerNumaNode := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.NumaMaximumMemorySizePerNode, 0) + if maxMemorySizePerNumaNode != 0 { + numa.MaxMemorySizePerNumaNode = &maxMemorySizePerNumaNode + } + + preferredPhysicalNumaNodes := oci.ParseAnnotationCommaSeparatedUint32(ctx, annotations, shimannotations.NumaPreferredPhysicalNodes, []uint32{}) + numa.PreferredPhysicalNumaNodes = preferredPhysicalNumaNodes + + numaMappedPhysicalNodes := oci.ParseAnnotationCommaSeparatedUint32(ctx, annotations, shimannotations.NumaMappedPhysicalNodes, []uint32{}) + numa.NumaMappedPhysicalNodes = numaMappedPhysicalNodes + + numaProcessorCounts := oci.ParseAnnotationCommaSeparatedUint32(ctx, annotations, shimannotations.NumaCountOfProcessors, []uint32{}) + numa.NumaProcessorCounts = numaProcessorCounts + + numaMemoryBlocksCount := oci.ParseAnnotationCommaSeparatedUint64(ctx, annotations, shimannotations.NumaCountOfMemoryBlocks, []uint64{}) + numa.NumaMemoryBlocksCounts = numaMemoryBlocksCount + + return numa, nil +} + +// parseAdditionalConfigurations parses additional configurations from annotations and options. +func parseAdditionalConfigurations(ctx context.Context, opts *runhcsoptions.Options, annotations map[string]string) (*AdditionalConfig, error) { + additionalConfig := &AdditionalConfig{} + + networkConfigProxy := oci.ParseAnnotationsString(annotations, shimannotations.NetworkConfigProxy, "") + if networkConfigProxy != "" { + additionalConfig.NetworkConfigProxy = &networkConfigProxy + } else if opts.NCProxyAddr != "" { + additionalConfig.NetworkConfigProxy = &opts.NCProxyAddr + } + + processDumpLocation := oci.ParseAnnotationsString(annotations, shimannotations.ContainerProcessDumpLocation, "") + if processDumpLocation != "" { + additionalConfig.ProcessDumpLocation = &processDumpLocation + } + + dumpDirectoryPath := oci.ParseAnnotationsString(annotations, shimannotations.DumpDirectoryPath, "") + if dumpDirectoryPath != "" { + additionalConfig.DumpDirectoryPath = &dumpDirectoryPath + } + + consolePipe := oci.ParseAnnotationsString(annotations, iannotations.UVMConsolePipe, "") + if consolePipe != "" { + additionalConfig.ConsolePipe = &consolePipe + } + + hvSocketServiceTable, err := parseHVSocketServiceTableFromAnnotations(ctx, annotations) + if err != nil { + return nil, fmt.Errorf("failed to parse HVSocket service table: %w", err) + } + additionalConfig.AdditionalHypervConfig = hvSocketServiceTable + + return additionalConfig, nil +} + +// parseHVSocketServiceTableFromAnnotations parses HVSocket service table from annotations. +func parseHVSocketServiceTableFromAnnotations(ctx context.Context, annotations map[string]string) (map[string]*HvSocketServiceConfig, error) { + hcsHvSocketServiceTable := oci.ParseHVSocketServiceTable(ctx, annotations) + if len(hcsHvSocketServiceTable) == 0 { + return make(map[string]*HvSocketServiceConfig), nil + } + + sc := make(map[string]*HvSocketServiceConfig, len(hcsHvSocketServiceTable)) + for name, entry := range hcsHvSocketServiceTable { + conf := &HvSocketServiceConfig{} + conf.BindSecurityDescriptor = &entry.BindSecurityDescriptor + conf.ConnectSecurityDescriptor = &entry.ConnectSecurityDescriptor + conf.AllowWildcardBinds = &entry.AllowWildcardBinds + conf.Disabled = &entry.Disabled + sc[name] = conf + } + + return sc, nil +} + +// parseLinuxBootOptions parses Linux boot options from annotations and options. +func parseLinuxBootOptions(ctx context.Context, opts *runhcsoptions.Options, annotations map[string]string) (*LinuxBootOptions, error) { + bootOptions := &LinuxBootOptions{} + + if _, ok := annotations[shimannotations.BootFilesRootPath]; ok { + bootFilesRootPath := oci.ParseAnnotationsString(annotations, shimannotations.BootFilesRootPath, "") + if bootFilesRootPath != "" { + bootOptions.BootFilesPath = &bootFilesRootPath + } + } else if opts.BootFilesRootPath != "" { + bootOptions.BootFilesPath = &opts.BootFilesRootPath + } + + kernelDirect := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.KernelDirectBoot) + bootOptions.KernelDirect = kernelDirect + + kernelBootOptions := oci.ParseAnnotationsString(annotations, shimannotations.KernelBootOptions, "") + if kernelBootOptions != "" { + bootOptions.KernelBootOptions = &kernelBootOptions + } + + enableColdDiscardHint := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.EnableColdDiscardHint) + bootOptions.EnableColdDiscardHint = enableColdDiscardHint + + hclEnabled := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.LCOWHclEnabled) + bootOptions.HclEnabled = hclEnabled + + preferredRootfsType := oci.ParseAnnotationsString(annotations, shimannotations.PreferredRootFSType, "") + if preferredRootfsType != "" { + var t PreferredRootFSType + switch preferredRootfsType { + case "initrd": + t = PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD + case "vhd": + t = PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_VHD + default: + return nil, fmt.Errorf("invalid PreferredRootFSType: %s", preferredRootfsType) + } + bootOptions.PreferredRootFsType = &t + } + + return bootOptions, nil +} + +// parseLinuxGuestOptions parses Linux guest options from annotations. +func parseLinuxGuestOptions(ctx context.Context, annotations map[string]string) (*LinuxGuestOptions, error) { + guestOptions := &LinuxGuestOptions{} + + disableTimeSyncService := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.DisableLCOWTimeSyncService) + guestOptions.DisableTimeSyncService = disableTimeSyncService + + networkingPolicyBasedRouting := oci.ParseAnnotationsNullableBool(ctx, annotations, iannotations.NetworkingPolicyBasedRouting) + guestOptions.PolicyBasedRouting = networkingPolicyBasedRouting + + writableOverlayDirs := oci.ParseAnnotationsNullableBool(ctx, annotations, iannotations.WritableOverlayDirs) + guestOptions.WritableOverlayDirs = writableOverlayDirs + + extraVsockPorts := oci.ParseAnnotationCommaSeparatedUint32(ctx, annotations, iannotations.ExtraVSockPorts, []uint32{}) + guestOptions.ExtraVsockPorts = extraVsockPorts + + return guestOptions, nil +} + +// parseLinuxDeviceOptions parses Linux device options from annotations. +func parseLinuxDeviceOptions(ctx context.Context, annotations map[string]string, devices []specs.WindowsDevice) (*LinuxDeviceOptions, error) { + deviceOptions := &LinuxDeviceOptions{} + + vpMemDeviceCount := oci.ParseAnnotationsUint32(ctx, annotations, shimannotations.VPMemCount, 0) + if vpMemDeviceCount != 0 { + deviceOptions.VpMemDeviceCount = &vpMemDeviceCount + } + + vpMemSizeBytes := oci.ParseAnnotationsUint64(ctx, annotations, shimannotations.VPMemSize, 0) + if vpMemSizeBytes != 0 { + deviceOptions.VpMemSizeBytes = &vpMemSizeBytes + } + + vpMemNoMultiMapping := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.VPMemNoMultiMapping) + deviceOptions.VpMemNoMultiMapping = vpMemNoMultiMapping + + vpciEnabled := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.VPCIEnabled) + deviceOptions.VpciEnabled = vpciEnabled + + devicesToAdd := make([]*Device, 0, len(devices)) + for _, dev := range devices { + devAdd := &Device{ + ID: dev.ID, + IdType: dev.IDType, + } + devicesToAdd = append(devicesToAdd, devAdd) + } + + deviceOptions.AssignedDevices = devicesToAdd + + return deviceOptions, nil +} + +// parseLinuxConfidentialOptions parses Linux confidential options from annotations. +func parseLinuxConfidentialOptions(ctx context.Context, annotations map[string]string) (*LCOWConfidentialOptions, error) { + lcowConfidentialOptions := &LCOWConfidentialOptions{} + + confidentialOptions := &ConfidentialOptions{} + + guestStateFile := oci.ParseAnnotationsString(annotations, shimannotations.LCOWGuestStateFile, "") + if guestStateFile != "" { + confidentialOptions.GuestStateFile = &guestStateFile + } + + securityPolicy := oci.ParseAnnotationsString(annotations, shimannotations.LCOWSecurityPolicy, "") + if securityPolicy != "" { + confidentialOptions.SecurityPolicy = &securityPolicy + } + + securityPolicyEnforcer := oci.ParseAnnotationsString(annotations, shimannotations.LCOWSecurityPolicyEnforcer, "") + if securityPolicyEnforcer != "" { + confidentialOptions.SecurityPolicyEnforcer = &securityPolicyEnforcer + } + + uvmReferenceInfoFile := oci.ParseAnnotationsString(annotations, shimannotations.LCOWReferenceInfoFile, "") + if uvmReferenceInfoFile != "" { + confidentialOptions.UvmReferenceInfoFile = &uvmReferenceInfoFile + } + + noSecurityHardware := oci.ParseAnnotationsBool(ctx, annotations, shimannotations.NoSecurityHardware, false) + confidentialOptions.NoSecurityHardware = &noSecurityHardware + + lcowConfidentialOptions.Options = confidentialOptions + + enableScratchEncryption := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.LCOWEncryptedScratchDisk) + lcowConfidentialOptions.EnableScratchEncryption = enableScratchEncryption + + dmVerityMode := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.DmVerityMode) + lcowConfidentialOptions.DmVerityMode = dmVerityMode + + dmVerityRootFsVhd := oci.ParseAnnotationsString(annotations, shimannotations.DmVerityRootFsVhd, "") + if dmVerityRootFsVhd != "" { + lcowConfidentialOptions.DmVerityRootFsVhd = &dmVerityRootFsVhd + } + + dmVerityCreateArgs := oci.ParseAnnotationsString(annotations, shimannotations.DmVerityCreateArgs, "") + if dmVerityCreateArgs != "" { + lcowConfidentialOptions.DmVerityCreateArgs = &dmVerityCreateArgs + } + + return lcowConfidentialOptions, nil +} + +// parseWindowsBootOptions parses Windows boot options from annotations. +func parseWindowsBootOptions(ctx context.Context, annotations map[string]string) (*WindowsBootOptions, error) { + bootOptions := &WindowsBootOptions{} + + disableCompartmentNamespace := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.DisableCompartmentNamespace) + bootOptions.DisableCompartmentNamespace = disableCompartmentNamespace + + noDirectMap := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.VSMBNoDirectMap) + bootOptions.NoDirectMap = noDirectMap + + return bootOptions, nil +} + +// parseWindowsGuestOptions parses Windows guest options from annotations. +func parseWindowsGuestOptions(ctx context.Context, annotations map[string]string) (*WindowsGuestOptions, error) { + guestOptions := &WindowsGuestOptions{} + + noInheritTimezone := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.NoInheritHostTimezone) + guestOptions.NoInheritHostTimezone = noInheritTimezone + + hcsRegistryKeys := oci.ParseAdditionalRegistryValues(ctx, annotations) + guestOptions.AdditionalRegistryKeys = registryValuesToProto(hcsRegistryKeys) + + forwardLogs := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.ForwardLogs) + guestOptions.ForwardLogs = forwardLogs + + logSources := oci.ParseAnnotationsString(annotations, shimannotations.LogSources, "") + if logSources != "" { + guestOptions.LogSources = &logSources + } + + return guestOptions, nil +} + +// parseWindowsConfidentialOptions parses Windows confidential options from annotations. +func parseWindowsConfidentialOptions(ctx context.Context, annotations map[string]string) (*WCOWConfidentialOptions, error) { + wcowConfidentialOptions := &WCOWConfidentialOptions{} + + confidentialOptions := &ConfidentialOptions{} + + securityPolicy := oci.ParseAnnotationsString(annotations, shimannotations.WCOWSecurityPolicy, "") + if securityPolicy != "" { + confidentialOptions.SecurityPolicy = &securityPolicy + } + + guestStateFile := oci.ParseAnnotationsString(annotations, shimannotations.WCOWGuestStateFile, "") + if guestStateFile != "" { + confidentialOptions.GuestStateFile = &guestStateFile + } + + securityPolicyEnforcer := oci.ParseAnnotationsString(annotations, shimannotations.WCOWSecurityPolicyEnforcer, "") + if securityPolicyEnforcer != "" { + confidentialOptions.SecurityPolicyEnforcer = &securityPolicyEnforcer + } + + uvmReferenceInfoFile := oci.ParseAnnotationsString(annotations, shimannotations.WCOWReferenceInfoFile, "") + if uvmReferenceInfoFile != "" { + confidentialOptions.UvmReferenceInfoFile = &uvmReferenceInfoFile + } + + noSecurityHardware := oci.ParseAnnotationsBool(ctx, annotations, shimannotations.NoSecurityHardware, false) + confidentialOptions.NoSecurityHardware = &noSecurityHardware + + wcowConfidentialOptions.Options = confidentialOptions + + writableEFI := oci.ParseAnnotationsNullableBool(ctx, annotations, shimannotations.WCOWWritableEFI) + wcowConfidentialOptions.WritableEfi = writableEFI + + disableSecureBoot := oci.ParseAnnotationsBool(ctx, annotations, shimannotations.WCOWDisableSecureBoot, false) + wcowConfidentialOptions.DisableSecureBoot = &disableSecureBoot + + isolationType := oci.ParseAnnotationsString(annotations, shimannotations.WCOWIsolationType, "") + if isolationType != "" { + wcowConfidentialOptions.IsolationType = &isolationType + } + + return wcowConfidentialOptions, nil +} + +// ----------------------------------------------------------------------------- +// Small utilities to reduce nil-check boilerplate +// ----------------------------------------------------------------------------- + +// splitPlatform expects "linux/amd64" or "windows/amd64" +// and splits it into osName and arch. +func splitPlatform(p string) (osName, arch string, err error) { + if p == "" { + return "", "", fmt.Errorf("sandbox_platform empty; expected \"linux/amd64\" or \"windows/amd64\"") + } + parts := strings.Split(p, "/") + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("invalid sandbox_platform %q; expected \"linux/amd64\" or \"windows/amd64\"", p) + } + return parts[0], parts[1], nil +} + +// Convert a slice of hcsschema.RegistryValue -> slice of *proto RegistryValue. +func registryValuesToProto(in []hcsschema.RegistryValue) []*RegistryValue { + out := make([]*RegistryValue, 0, len(in)) + for _, reg := range in { + var key *RegistryKey + if reg.Key != nil { + key = &RegistryKey{ + Hive: mapHcsHiveToProto(reg.Key.Hive), + Name: strings.TrimSpace(reg.Key.Name), + Volatile: reg.Key.Volatile, + } + } + + rv := &RegistryValue{ + Key: key, + Name: strings.TrimSpace(reg.Name), + Type: mapHcsRegValueTypeToProto(reg.Type_), + StringValue: reg.StringValue, + BinaryValue: reg.BinaryValue, + DwordValue: reg.DWordValue, + QwordValue: reg.QWordValue, + CustomType: reg.CustomType, + } + + out = append(out, rv) + } + return out +} + +// Map hcsschema.RegistryHive -> proto RegistryHive. +func mapHcsHiveToProto(h hcsschema.RegistryHive) RegistryHive { + switch h { + case hcsschema.RegistryHive_SYSTEM: + return RegistryHive_REGISTRY_HIVE_SYSTEM + case hcsschema.RegistryHive_SOFTWARE: + return RegistryHive_REGISTRY_HIVE_SOFTWARE + case hcsschema.RegistryHive_SECURITY: + return RegistryHive_REGISTRY_HIVE_SECURITY + case hcsschema.RegistryHive_SAM: + return RegistryHive_REGISTRY_HIVE_SAM + default: + // Choose a sensible default. SYSTEM matches your proto->HCS default. + return RegistryHive_REGISTRY_HIVE_SYSTEM + } +} + +// Map hcsschema.RegistryValueType -> proto RegistryValueType. +func mapHcsRegValueTypeToProto(t hcsschema.RegistryValueType) RegistryValueType { + switch t { + case hcsschema.RegistryValueType_NONE: + return RegistryValueType_REGISTRY_VALUE_TYPE_NONE + case hcsschema.RegistryValueType_STRING: + return RegistryValueType_REGISTRY_VALUE_TYPE_STRING + case hcsschema.RegistryValueType_EXPANDED_STRING: + return RegistryValueType_REGISTRY_VALUE_TYPE_EXPANDED_STRING + case hcsschema.RegistryValueType_MULTI_STRING: + return RegistryValueType_REGISTRY_VALUE_TYPE_MULTI_STRING + case hcsschema.RegistryValueType_BINARY: + return RegistryValueType_REGISTRY_VALUE_TYPE_BINARY + case hcsschema.RegistryValueType_D_WORD: + return RegistryValueType_REGISTRY_VALUE_TYPE_D_WORD + case hcsschema.RegistryValueType_Q_WORD: + return RegistryValueType_REGISTRY_VALUE_TYPE_Q_WORD + case hcsschema.RegistryValueType_CUSTOM_TYPE: + return RegistryValueType_REGISTRY_VALUE_TYPE_CUSTOM_TYPE + default: + return RegistryValueType_REGISTRY_VALUE_TYPE_NONE + } +} diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs_test.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs_test.go new file mode 100644 index 0000000000..d21ae2e9bd --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/sandbox_specs_test.go @@ -0,0 +1,836 @@ +package sandboxspec + +import ( + "encoding/json" + "testing" + + "google.golang.org/protobuf/proto" + + runhcsoptions "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" + iannotations "github.com/Microsoft/hcsshim/internal/annotations" + shimannotations "github.com/Microsoft/hcsshim/pkg/annotations" + + "github.com/opencontainers/runtime-spec/specs-go" +) + +// ptr is a helper to return a pointer to a value. +// Required for initializing optional pointer fields in structs. +func ptr[T any](v T) *T { + return &v +} + +func TestGenerateSpecss(t *testing.T) { + type testCase struct { + name string + opts *runhcsoptions.Options + annotations map[string]string + devices []specs.WindowsDevice + expected *Specs + expectError bool + } + + tests := []testCase{ + // ==================================================================== + // SECTION 1: LCOW (Linux) Specific Tests + // ==================================================================== + { + name: "LCOW_Boot_And_Guest_Options_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + // Boot Options + shimannotations.KernelBootOptions: "debug", + shimannotations.KernelDirectBoot: "true", + shimannotations.LCOWHclEnabled: "true", + shimannotations.EnableColdDiscardHint: "true", + shimannotations.PreferredRootFSType: "initrd", + shimannotations.BootFilesRootPath: "/boot/files", + // Guest Options + shimannotations.DisableLCOWTimeSyncService: "true", + iannotations.NetworkingPolicyBasedRouting: "true", + iannotations.WritableOverlayDirs: "true", + iannotations.ExtraVSockPorts: "1024,2048", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{ + KernelBootOptions: ptr("debug"), + KernelDirect: ptr(true), + HclEnabled: ptr(true), + EnableColdDiscardHint: ptr(true), + PreferredRootFsType: ptr(PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD), + BootFilesPath: ptr("/boot/files"), + }, + LinuxGuestOptions: &LinuxGuestOptions{ + DisableTimeSyncService: ptr(true), + PolicyBasedRouting: ptr(true), + WritableOverlayDirs: ptr(true), + ExtraVsockPorts: []uint32{1024, 2048}, + }, + LinuxDeviceOptions: &LinuxDeviceOptions{ + AssignedDevices: []*Device{}, + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "LCOW_DeviceOptions_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + shimannotations.VPMemCount: "4", + shimannotations.VPMemSize: "1073741824", // 1GiB + shimannotations.VPCIEnabled: "true", + shimannotations.VPMemNoMultiMapping: "true", + }, + devices: []specs.WindowsDevice{ + {ID: "1111-1111", IDType: "class"}, + {ID: "2222-2222", IDType: "class"}, + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ExtraVsockPorts: []uint32{}}, + LinuxDeviceOptions: &LinuxDeviceOptions{ + VpMemDeviceCount: ptr(uint32(4)), + VpMemSizeBytes: ptr(uint64(1073741824)), + VpciEnabled: ptr(true), + VpMemNoMultiMapping: ptr(true), + AssignedDevices: []*Device{ + {ID: "1111-1111", IdType: "class"}, + {ID: "2222-2222", IdType: "class"}, + }, + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "LCOW_Confidential_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + shimannotations.LCOWGuestStateFile: "guest_state.vmgs", + shimannotations.LCOWSecurityPolicy: "abc123", + shimannotations.LCOWSecurityPolicyEnforcer: "XYZ", + shimannotations.LCOWReferenceInfoFile: "uvm_ref_info.json", + shimannotations.NoSecurityHardware: "false", + shimannotations.DmVerityMode: "true", + shimannotations.DmVerityRootFsVhd: "/host/paths/rootfs.vhd", + shimannotations.DmVerityCreateArgs: "1 /dev/vda1 /dev/vda2", + shimannotations.LCOWEncryptedScratchDisk: "true", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ExtraVsockPorts: []uint32{}}, + LinuxDeviceOptions: &LinuxDeviceOptions{AssignedDevices: []*Device{}}, + ConfidentialOptions: &LCOWConfidentialOptions{ + DmVerityMode: ptr(true), + DmVerityRootFsVhd: ptr("/host/paths/rootfs.vhd"), + DmVerityCreateArgs: ptr("1 /dev/vda1 /dev/vda2"), + EnableScratchEncryption: ptr(true), + Options: &ConfidentialOptions{ + NoSecurityHardware: ptr(false), + GuestStateFile: ptr("guest_state.vmgs"), + SecurityPolicy: ptr("abc123"), + SecurityPolicyEnforcer: ptr("XYZ"), + UvmReferenceInfoFile: ptr("uvm_ref_info.json"), + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "LCOW_RunHCSOptions_Override", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + // Use boot files from Options when annotation is missing. + BootFilesRootPath: "/default/boot/files", + VmProcessorCount: 4, + VmMemorySizeInMb: 100, + NCProxyAddr: "//./pipe/proxy", + }, + annotations: map[string]string{}, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{ + ProcessorCount: ptr(int32(4)), + Architecture: ptr("amd64"), + }, + MemoryConfig: &MemoryConfig{ + MemorySizeInMb: ptr(uint64(100)), + }, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{ + NetworkConfigProxy: ptr("//./pipe/proxy"), + }, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{ + BootFilesPath: ptr("/default/boot/files"), + }, + LinuxGuestOptions: &LinuxGuestOptions{ + ExtraVsockPorts: []uint32{}, + }, + LinuxDeviceOptions: &LinuxDeviceOptions{ + AssignedDevices: []*Device{}, + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "LCOW_MissingValues", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{}, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ + ExtraVsockPorts: []uint32{}, + }, + LinuxDeviceOptions: &LinuxDeviceOptions{ + AssignedDevices: []*Device{}, + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + + // ==================================================================== + // SECTION 2: WCOW (Windows) Specific Tests + // ==================================================================== + { + name: "WCOW_Boot_Guest_And_Registry", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{ + // Boot Options + shimannotations.DisableCompartmentNamespace: "true", + shimannotations.VSMBNoDirectMap: "true", + // Guest Options + shimannotations.NoInheritHostTimezone: "true", + // Registry + iannotations.AdditionalRegistryValues: `[ + { + "Key": {"Hive": "Software", "Name": "Software\\TestKey"}, + "Name": "TestVal", + "Type": "String", + "StringValue": "MyValue" + } + ]`, + shimannotations.ForwardLogs: "true", + shimannotations.LogSources: "Microsoft-Windows-Containers-GuestLog", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{ + DisableCompartmentNamespace: ptr(true), + NoDirectMap: ptr(true), + }, + WindowsGuestOptions: &WindowsGuestOptions{ + NoInheritHostTimezone: ptr(true), + AdditionalRegistryKeys: []*RegistryValue{ + { + Key: &RegistryKey{ + Hive: RegistryHive_REGISTRY_HIVE_SOFTWARE, + Name: "Software\\TestKey", + }, + Name: "TestVal", + Type: RegistryValueType_REGISTRY_VALUE_TYPE_STRING, + StringValue: "MyValue", + }, + }, + ForwardLogs: ptr(true), + LogSources: ptr("Microsoft-Windows-Containers-GuestLog"), + }, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + { + name: "WCOW_Confidential_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{ + shimannotations.WCOWDisableSecureBoot: "true", + shimannotations.WCOWWritableEFI: "true", + shimannotations.WCOWIsolationType: "NoIsolation", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(true), + WritableEfi: ptr(true), + IsolationType: ptr("NoIsolation"), + }, + }, + }, + }, + }, + }, + }, + { + name: "WCOW_MissingValues", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{}, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + + // ==================================================================== + // SECTION 3: Common Resources (Memory, Storage, Additional) + // ==================================================================== + { + name: "Memory_Storage_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + // Memory + shimannotations.MemorySizeInMB: "2048", + shimannotations.MemoryLowMMIOGapInMB: "128", + shimannotations.MemoryHighMMIOBaseInMB: "512", + shimannotations.MemoryHighMMIOGapInMB: "256", + shimannotations.AllowOvercommit: "false", + shimannotations.FullyPhysicallyBacked: "true", + shimannotations.EnableDeferredCommit: "true", + // Storage + shimannotations.DisableWritableFileShares: "true", + shimannotations.StorageQoSBandwidthMaximum: "1048576", // 1MB/s + shimannotations.StorageQoSIopsMaximum: "500", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{ + MemorySizeInMb: ptr(uint64(2048)), + LowMmioGapInMb: ptr(uint64(128)), + HighMmioBaseInMb: ptr(uint64(512)), + HighMmioGapInMb: ptr(uint64(256)), + AllowOvercommit: ptr(false), + FullyPhysicallyBacked: ptr(true), + EnableDeferredCommit: ptr(true), + }, + StorageConfig: &StorageConfig{ + NoWritableFileShares: ptr(true), + StorageQosBandwidthMaximum: ptr(int32(1048576)), + StorageQosIopsMaximum: ptr(int32(500)), + }, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ExtraVsockPorts: []uint32{}}, + LinuxDeviceOptions: &LinuxDeviceOptions{AssignedDevices: []*Device{}}, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "AdditionalConfig_Comprehensive", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{ + shimannotations.NetworkConfigProxy: "//./pipe/proxy", + shimannotations.ContainerProcessDumpLocation: "C:\\dumps", + shimannotations.DumpDirectoryPath: "C:\\host\\dumps", + iannotations.UVMConsolePipe: "\\\\.\\pipe\\vm-console", + "io.microsoft.virtualmachine.hv-socket.service-table.00000000-0000-0000-0000-000000000001": `{"AllowWildcardBinds": true, "BindSecurityDescriptor": "D:P(A;;FA;;;WD)"}`, + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{ + NetworkConfigProxy: ptr("//./pipe/proxy"), + ProcessDumpLocation: ptr("C:\\dumps"), + DumpDirectoryPath: ptr("C:\\host\\dumps"), + ConsolePipe: ptr("\\\\.\\pipe\\vm-console"), + AdditionalHypervConfig: map[string]*HvSocketServiceConfig{ + "00000000-0000-0000-0000-000000000001": { + AllowWildcardBinds: ptr(true), + BindSecurityDescriptor: ptr("D:P(A;;FA;;;WD)"), + ConnectSecurityDescriptor: ptr(""), + Disabled: ptr(false), + }, + }, + }, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + + // ==================================================================== + // SECTION 4: Logic, Precedence and Error Handling + // ==================================================================== + { + name: "Mixed_Defaults_And_Overrides_Logic", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + // Default annotations passed via Options + DefaultContainerAnnotations: map[string]string{ + shimannotations.ProcessorCount: "2", + shimannotations.StorageQoSIopsMaximum: "100", + }, + }, + annotations: map[string]string{ + // This should OVERRIDE the DefaultContainerAnnotations above + shimannotations.ProcessorCount: "8", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{ + Architecture: ptr("amd64"), + ProcessorCount: ptr(int32(8)), // Overridden + }, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{ + StorageQosIopsMaximum: ptr(int32(100)), // From default + }, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + { + name: "Explicit_NUMA_Topology", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + shimannotations.NumaMappedPhysicalNodes: "0,1", + shimannotations.NumaCountOfProcessors: "4,4", + shimannotations.NumaCountOfMemoryBlocks: "8192,8192", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{ + NumaMappedPhysicalNodes: []uint32{0, 1}, + NumaProcessorCounts: []uint32{4, 4}, + NumaMemoryBlocksCounts: []uint64{8192, 8192}, + }, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ExtraVsockPorts: []uint32{}}, + LinuxDeviceOptions: &LinuxDeviceOptions{AssignedDevices: []*Device{}}, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "CPUGroup_And_ResourcePartition", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{ + shimannotations.CPUGroupID: "cg-123", + shimannotations.ResourcePartitionID: "rp-abc", + }, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + CpuGroupID: ptr("cg-123"), + ResourcePartitionID: ptr("rp-abc"), + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + + // ==================================================================== + // SECTION 5: Edge Cases, Nil Checks, and Errors + // ==================================================================== + { + name: "ProcessIsolation_Returns_ProcessSpec", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_PROCESS, + }, + annotations: nil, + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Process{ + Process: &ProcessIsolated{}, + }, + }, + }, + { + name: "NilOptions_ShouldError", + opts: nil, + annotations: map[string]string{}, + expectError: true, + expected: nil, + }, + { + name: "Platform_Empty_ShouldError", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "", + }, + annotations: map[string]string{}, + expectError: true, + expected: nil, + }, + { + name: "Platform_UnsupportedOS_ShouldError", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "darwin/arm64", + }, + annotations: map[string]string{}, + expectError: true, + expected: nil, + }, + { + name: "LinuxBoot_PreferredRootFSType_Invalid_ShouldError", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + shimannotations.PreferredRootFSType: "not-a-valid-type", + }, + expectError: true, + expected: nil, + }, + { + name: "Safety_Garbage_Inputs_ShouldNotPanic", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "linux/amd64", + }, + annotations: map[string]string{ + shimannotations.ProcessorCount: "NOT_A_NUMBER", + shimannotations.MemorySizeInMB: "-100", + shimannotations.NumaPreferredPhysicalNodes: "garbage,data", + }, + expectError: false, + // Should return a valid default spec because parsing errors are logged + // and ignored (returning default values like 0/nil). + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{}, + LinuxGuestOptions: &LinuxGuestOptions{ExtraVsockPorts: []uint32{}}, + LinuxDeviceOptions: &LinuxDeviceOptions{AssignedDevices: []*Device{}}, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + }, + }, + }, + }, + }, + }, + }, + { + name: "Safety_Nil_Maps_And_Slices", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: nil, // Nil annotations map + devices: nil, // Nil devices slice + expectError: false, + expected: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + StorageConfig: &StorageConfig{}, + NumaConfig: &NUMAConfig{}, + AdditionalConfig: &AdditionalConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{}, + WindowsGuestOptions: &WindowsGuestOptions{AdditionalRegistryKeys: []*RegistryValue{}}, + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{NoSecurityHardware: ptr(false)}, + DisableSecureBoot: ptr(false), + }, + }, + }, + }, + }, + }, + }, + + // ==================================================================== + // SECTION 6: NEGATIVE TEST CASES (Expect Errors) + // ==================================================================== + { + name: "Negative_Conflicting_HostProcess_Annotations", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/amd64", + }, + annotations: map[string]string{ + shimannotations.HostProcessContainer: "true", + shimannotations.DisableHostProcessContainer: "true", + }, + expectError: true, + expected: nil, + }, + { + name: "Negative_Invalid_Platform_Format_NoSlash", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows_amd64", + }, + annotations: map[string]string{}, + expectError: true, + expected: nil, + }, + { + name: "Negative_Invalid_Platform_Format_MissingArch", + opts: &runhcsoptions.Options{ + SandboxIsolation: runhcsoptions.Options_HYPERVISOR, + SandboxPlatform: "windows/", + }, + annotations: map[string]string{}, + expectError: true, + expected: nil, + }, + } + + for _, tt := range tests { + safeTestRun(t, tt.name, func(t *testing.T) { + t.Helper() + got, err := Generate(tt.opts, tt.annotations, tt.devices) + + // 1. Error Validation + if tt.expectError { + if err == nil { + t.Error("Expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // 2. Golden Object Comparison using proto.Equal + if !proto.Equal(got, tt.expected) { + // Since we can't use cmp.Diff, we use JSON for a readable diff in the error logs + gotJSON, _ := json.MarshalIndent(got, "", " ") + wantJSON, _ := json.MarshalIndent(tt.expected, "", " ") + t.Errorf("GenerateSpecss() mismatch.\nGot:\n%s\n\nWant:\n%s", gotJSON, wantJSON) + } + }) + } +} + +// safeTestRun wraps the test execution to catch any panics. +func safeTestRun(t *testing.T, name string, testFunc func(t *testing.T)) { + t.Helper() + t.Run(name, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Fatalf("PANIC DETECTED in test case '%s': %v", name, r) + } + }() + testFunc(t) + }) +} diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs.go new file mode 100644 index 0000000000..858b9f961a --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs.go @@ -0,0 +1,627 @@ +//go:build windows + +package sandboxspec + +import ( + "context" + "fmt" + "maps" + "runtime" + "strings" + + "github.com/Microsoft/go-winio/pkg/guid" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/oci" + "github.com/Microsoft/hcsshim/internal/uvm" + "github.com/containerd/platforms" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/sirupsen/logrus" +) + +var ( + // linuxPlatformFormat represents the format for linux platform. + // Example: linux/amd64 + linuxPlatformFormat = "linux/%s" + // windowsPlatformFormat represents the format for windows platform. + // Example: windows/amd64 + windowsPlatformFormat = "windows/%s" +) + +// BuildUVMOptions creates either LCOW or WCOW options from Specs. +// Defaults are set by NewDefaultOptionsLCOW/NewDefaultOptionsWCOW and +// then overridden by any fields present in the proto. +func BuildUVMOptions(ctx context.Context, spec *Specs, id, owner string) (*uvm.OptionsLCOW, *uvm.OptionsWCOW, *platforms.Platform, error) { + if spec == nil { + return nil, nil, nil, fmt.Errorf("nil sandbox specs") + } + + switch isolation := spec.IsolationLevel.(type) { + case *Specs_Process: + // Process isolation: no UVM to create. + return nil, nil, nil, fmt.Errorf("uvm options cannot be created for process isolation") + + case *Specs_Hypervisor: + hypervisor := isolation.Hypervisor + if hypervisor == nil { + return nil, nil, nil, fmt.Errorf("hypervisor section is nil for isolation_level=hypervisor") + } + + switch platform := hypervisor.Platform.(type) { + case *HypervisorIsolated_Lcow: + if platform.Lcow == nil { + return nil, nil, nil, fmt.Errorf("lcow params are nil for isolation_level=hypervisor") + } + + var plat *platforms.Platform + var err error + + optionsLCOW := uvm.NewDefaultOptionsLCOW(id, owner) + + // Platform-specific overlays + if lb := platform.Lcow.GetLinuxBootOptions(); lb != nil { + applyLinuxBootOptions(ctx, optionsLCOW, lb) + } + if lg := platform.Lcow.GetLinuxGuestOptions(); lg != nil { + applyLinuxGuestOptions(optionsLCOW, lg) + } + if ld := platform.Lcow.GetLinuxDeviceOptions(); ld != nil { + if err = applyLinuxDeviceOptions(ctx, optionsLCOW, ld); err != nil { + return nil, nil, nil, err + } + } + + // Common overlays + if cpu := hypervisor.GetCpuConfig(); cpu != nil { + applyCPUConfig(optionsLCOW.Options, cpu) + plat, err = parsePlatform(cpu, true) + if err != nil { + return nil, nil, nil, err + } + } + if mem := hypervisor.GetMemoryConfig(); mem != nil { + applyMemoryConfig(optionsLCOW.Options, mem) + + if hypervisor.MemoryConfig.FullyPhysicallyBacked != nil && *hypervisor.MemoryConfig.FullyPhysicallyBacked { + optionsLCOW.AllowOvercommit = false + optionsLCOW.VPMemDeviceCount = 0 + } + } + if sto := hypervisor.GetStorageConfig(); sto != nil { + applyStorageConfig(optionsLCOW.Options, sto) + } + if numa := hypervisor.GetNumaConfig(); numa != nil { + applyNUMAConfig(optionsLCOW.Options, numa) + } + + if add := hypervisor.GetAdditionalConfig(); add != nil { + applyAdditionalConfig(ctx, optionsLCOW.Options, add) + } + + if err = applyHypervisorConfig(optionsLCOW.Options, hypervisor); err != nil { + return nil, nil, nil, err + } + // LCOW Confidential options + if lc := platform.Lcow.GetConfidentialOptions(); lc != nil { + applyLCOWConfidentialOptions(optionsLCOW, lc) + } + + return optionsLCOW, nil, plat, nil + + case *HypervisorIsolated_Wcow: + if platform.Wcow == nil { + return nil, nil, nil, fmt.Errorf("wcow params are nil for isolation_level=hypervisor") + } + + var plat *platforms.Platform + var err error + + optionsWCOW := uvm.NewDefaultOptionsWCOW(id, owner) + + // Platform-specific overlays + wb := platform.Wcow.GetWindowsBootOptions() + if wb != nil { + applyWindowsBootOptions(optionsWCOW, wb) + } + + wg := platform.Wcow.GetWindowsGuestOptions() + if wg != nil { + if err = applyWindowsGuestOptions(ctx, optionsWCOW, wg); err != nil { + return nil, nil, nil, err + } + } + + // Common overlays + if cpu := hypervisor.GetCpuConfig(); cpu != nil { + applyCPUConfig(optionsWCOW.Options, cpu) + plat, err = parsePlatform(cpu, false) + if err != nil { + return nil, nil, nil, err + } + } + if mem := hypervisor.GetMemoryConfig(); mem != nil { + applyMemoryConfig(optionsWCOW.Options, mem) + + if hypervisor.MemoryConfig.FullyPhysicallyBacked != nil && *hypervisor.MemoryConfig.FullyPhysicallyBacked { + optionsWCOW.AllowOvercommit = false + } + } + if sto := hypervisor.GetStorageConfig(); sto != nil { + applyStorageConfig(optionsWCOW.Options, sto) + } + if numa := hypervisor.GetNumaConfig(); numa != nil { + applyNUMAConfig(optionsWCOW.Options, numa) + } + if add := hypervisor.GetAdditionalConfig(); add != nil { + applyAdditionalConfig(ctx, optionsWCOW.Options, add) + } + + if err = applyHypervisorConfig(optionsWCOW.Options, hypervisor); err != nil { + return nil, nil, nil, err + } + + // WCOW Confidential options + if wc := platform.Wcow.GetConfidentialOptions(); wc != nil { + err = applyWCOWConfidentialOptions(optionsWCOW, wc, wg, hypervisor.GetMemoryConfig()) + if err != nil { + return nil, nil, nil, err + } + } + + return nil, optionsWCOW, plat, nil + + default: + return nil, nil, nil, fmt.Errorf("hypervisor.platform must be LCOW or WCOW") + } + + default: + return nil, nil, nil, fmt.Errorf("unknown isolation_level") + } +} + +// ----------------------------------------------------------------------------- +// Common overlays +// ----------------------------------------------------------------------------- + +func applyCPUConfig(common *uvm.Options, cpu *CPUConfig) { + // processor_count: unset => keep defaults; set==0 => error + if cpu.ProcessorCount != nil && *cpu.ProcessorCount > 0 { + common.ProcessorCount = *cpu.ProcessorCount + } + + // processor_limit: unset => keep defaults; set==0 => error + if cpu.ProcessorLimit != nil && *cpu.ProcessorLimit > 0 { + common.ProcessorLimit = *cpu.ProcessorLimit + } + + // processor_weight: unset => keep defaults; set==0 => error + if cpu.ProcessorWeight != nil && *cpu.ProcessorWeight > 0 { + common.ProcessorWeight = *cpu.ProcessorWeight + } +} + +func parsePlatform(cpu *CPUConfig, isLinux bool) (*platforms.Platform, error) { + arch := runtime.GOARCH + if cpu.Architecture != nil { + arch = *cpu.Architecture + } + + var plat platforms.Platform + var err error + if isLinux { + plat, err = platforms.Parse(fmt.Sprintf(linuxPlatformFormat, arch)) + } else { + plat, err = platforms.Parse(fmt.Sprintf(windowsPlatformFormat, arch)) + } + + if err != nil { + return nil, fmt.Errorf("failed to parse platform: %w", err) + } + + return &plat, nil +} + +func applyMemoryConfig(common *uvm.Options, mem *MemoryConfig) { + // Additional check to ensure that Memory Size is non-zero. + if mem.MemorySizeInMb != nil && *mem.MemorySizeInMb > 0 { + common.MemorySizeInMB = *mem.MemorySizeInMb + } + + // MMIO: only overlay when non-zero in proto (your defaults are zero unless tuned) + setU64(&common.LowMMIOGapInMB, mem.LowMmioGapInMb) + setU64(&common.HighMMIOBaseInMB, mem.HighMmioBaseInMb) + setU64(&common.HighMMIOGapInMB, mem.HighMmioGapInMb) + + setBool(&common.AllowOvercommit, mem.AllowOvercommit) + setBool(&common.FullyPhysicallyBacked, mem.FullyPhysicallyBacked) + setBool(&common.EnableDeferredCommit, mem.EnableDeferredCommit) +} + +func applyStorageConfig(common *uvm.Options, sto *StorageConfig) { + if sto.StorageQosIopsMaximum != nil && *sto.StorageQosIopsMaximum > 0 { + common.StorageQoSIopsMaximum = *sto.StorageQosIopsMaximum + } + + if sto.StorageQosBandwidthMaximum != nil && *sto.StorageQosBandwidthMaximum > 0 { + common.StorageQoSBandwidthMaximum = *sto.StorageQosBandwidthMaximum + } + + setBool(&common.NoWritableFileShares, sto.NoWritableFileShares) +} + +func applyNUMAConfig(common *uvm.Options, n *NUMAConfig) { + setU32(&common.MaxProcessorsPerNumaNode, n.MaxProcessorsPerNumaNode) + setU64(&common.MaxMemorySizePerNumaNode, n.MaxMemorySizePerNumaNode) + + if len(n.PreferredPhysicalNumaNodes) > 0 { + common.PreferredPhysicalNumaNodes = copyU32(n.PreferredPhysicalNumaNodes) + } + if len(n.NumaMappedPhysicalNodes) > 0 { + common.NumaMappedPhysicalNodes = copyU32(n.NumaMappedPhysicalNodes) + } + if len(n.NumaProcessorCounts) > 0 { + common.NumaProcessorCounts = copyU32(n.NumaProcessorCounts) + } + if len(n.NumaMemoryBlocksCounts) > 0 { + common.NumaMemoryBlocksCounts = copyU64(n.NumaMemoryBlocksCounts) + } +} + +func applyAdditionalConfig(ctx context.Context, common *uvm.Options, a *AdditionalConfig) { + setStr(&common.NetworkConfigProxy, a.NetworkConfigProxy) + setStr(&common.ProcessDumpLocation, a.ProcessDumpLocation) + setStr(&common.DumpDirectoryPath, a.DumpDirectoryPath) + setStr(&common.ConsolePipe, a.ConsolePipe) + + if len(a.AdditionalHypervConfig) > 0 { + maps.Copy(common.AdditionalHyperVConfig, parseHVSocketServiceTable(ctx, a.AdditionalHypervConfig)) + } +} + +func parseHVSocketServiceTable(ctx context.Context, hyperVConfig map[string]*HvSocketServiceConfig) map[string]hcsschema.HvSocketServiceConfig { + parsedServiceTable := make(map[string]hcsschema.HvSocketServiceConfig) + + for key, val := range hyperVConfig { + parsedGUID, err := guid.FromString(key) + if err != nil { + log.G(ctx).WithError(err).Warn("invalid GUID string for Hyper-V socket service configuration annotation") + continue + } + guidStr := parsedGUID.String() // overwrite the GUID string to standardize format (capitalization) + + cfg := hcsschema.HvSocketServiceConfig{} + setStr(&cfg.BindSecurityDescriptor, val.BindSecurityDescriptor) + setStr(&cfg.ConnectSecurityDescriptor, val.ConnectSecurityDescriptor) + setBool(&cfg.AllowWildcardBinds, val.AllowWildcardBinds) + setBool(&cfg.Disabled, val.Disabled) + + if _, found := parsedServiceTable[guidStr]; found { + log.G(ctx).WithFields(logrus.Fields{ + "guid": guidStr, + }).Warn("overwritting existing Hyper-V socket service configuration") + } + + if log.G(ctx).Logger.IsLevelEnabled(logrus.TraceLevel) { + log.G(ctx).WithField("configuration", log.Format(ctx, cfg)).Trace("found Hyper-V socket service configuration annotation") + } + + parsedServiceTable[guidStr] = cfg + } + + return parsedServiceTable +} + +func applyHypervisorConfig(common *uvm.Options, hypervisor *HypervisorIsolated) error { + setStr(&common.CPUGroupID, hypervisor.CpuGroupID) + + if hypervisor.ResourcePartitionID != nil { + resourcePartitionID := *hypervisor.ResourcePartitionID + resourcePartitionIDGUID, err := guid.FromString(resourcePartitionID) + if err != nil { + return fmt.Errorf("failed to parse resource partition id %q to GUID: %w", resourcePartitionID, err) + } + common.ResourcePartitionID = &resourcePartitionIDGUID + } + + return nil +} + +// ----------------------------------------------------------------------------- +// LCOW overlays +// ----------------------------------------------------------------------------- + +func applyLinuxBootOptions(ctx context.Context, opts *uvm.OptionsLCOW, lb *LinuxBootOptions) { + setBool(&opts.EnableColdDiscardHint, lb.EnableColdDiscardHint) + + if lb.BootFilesPath != nil { + // Prefer the helper to update associated fields automatically. + opts.UpdateBootFilesPath(ctx, *lb.BootFilesPath) + } + + setStr(&opts.KernelBootOptions, lb.KernelBootOptions) + + setBool(&opts.KernelDirect, lb.KernelDirect) + if !opts.KernelDirect { + opts.KernelFile = uvm.KernelFile + } + + if lb.PreferredRootFsType != nil { + switch *lb.PreferredRootFsType { + case PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD: + opts.PreferredRootFSType = uvm.PreferredRootFSTypeInitRd + case PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_VHD: + opts.PreferredRootFSType = uvm.PreferredRootFSTypeVHD + default: + log.G(ctx).Warn("PreferredRootFsType must be 'initrd' or 'vhd'") + } + } + + switch opts.PreferredRootFSType { + case uvm.PreferredRootFSTypeInitRd: + opts.RootFSFile = uvm.InitrdFile + case uvm.PreferredRootFSTypeVHD: + opts.RootFSFile = uvm.VhdFile + } + + // HCL is presence-aware + if lb.HclEnabled != nil { + val := *lb.HclEnabled + opts.HclEnabled = &val + } else { + opts.HclEnabled = nil + } +} + +func applyLinuxGuestOptions(opts *uvm.OptionsLCOW, lg *LinuxGuestOptions) { + setBool(&opts.DisableTimeSyncService, lg.DisableTimeSyncService) + + if len(lg.ExtraVsockPorts) > 0 { + opts.ExtraVSockPorts = copyU32(lg.ExtraVsockPorts) + } + setBool(&opts.PolicyBasedRouting, lg.PolicyBasedRouting) + setBool(&opts.WritableOverlayDirs, lg.WritableOverlayDirs) +} + +func applyLinuxDeviceOptions(ctx context.Context, opts *uvm.OptionsLCOW, ld *LinuxDeviceOptions) error { + setU32(&opts.VPMemDeviceCount, ld.VpMemDeviceCount) + setU64(&opts.VPMemSizeBytes, ld.VpMemSizeBytes) + setBool(&opts.VPMemNoMultiMapping, ld.VpMemNoMultiMapping) + setBool(&opts.VPCIEnabled, ld.VpciEnabled) + + windowsDevices := make([]specs.WindowsDevice, 0, len(ld.AssignedDevices)) + for _, device := range ld.AssignedDevices { + windowsDevices = append(windowsDevices, specs.WindowsDevice{ + ID: device.ID, + IDType: device.IdType, + }) + } + opts.AssignedDevices = oci.ParseDevices(ctx, windowsDevices) + + return nil +} + +func applyLCOWConfidentialOptions(opts *uvm.OptionsLCOW, lc *LCOWConfidentialOptions) { + if lc.Options != nil { + applyCommonConfidentialLCOW(opts.ConfidentialLCOWOptions, lc.Options) + } + + setStr(&opts.GuestStateFile, lc.Options.GuestStateFile) + setStr(&opts.DmVerityRootFsVhd, lc.DmVerityRootFsVhd) + setBool(&opts.DmVerityMode, lc.DmVerityMode) + setStr(&opts.DmVerityCreateArgs, lc.DmVerityCreateArgs) + + if lc.Options.NoSecurityHardware != nil { + oci.HandleLCOWSecurityPolicyWithNoSecurityHardware(*lc.Options.NoSecurityHardware, opts) + } + + if len(opts.SecurityPolicy) > 0 { + opts.EnableScratchEncryption = true + setBool(&opts.EnableScratchEncryption, lc.EnableScratchEncryption) + } +} + +// ----------------------------------------------------------------------------- +// WCOW overlays +// ----------------------------------------------------------------------------- + +func applyWindowsBootOptions(opts *uvm.OptionsWCOW, wb *WindowsBootOptions) { + setBool(&opts.DisableCompartmentNamespace, wb.DisableCompartmentNamespace) + setBool(&opts.NoDirectMap, wb.NoDirectMap) +} + +func applyWindowsGuestOptions(ctx context.Context, opts *uvm.OptionsWCOW, wg *WindowsGuestOptions) error { + setBool(&opts.NoInheritHostTimezone, wg.NoInheritHostTimezone) + + if len(wg.AdditionalRegistryKeys) != 0 { + opts.AdditionalRegistryKeys = append(opts.AdditionalRegistryKeys, + oci.ValidateAndFilterRegistryValues(ctx, registryValuesFromProto(wg))...) + } + + setBool(&opts.ForwardLogs, wg.ForwardLogs) + setStr(&opts.LogSources, wg.LogSources) + + return nil +} + +func applyWCOWConfidentialOptions( + opts *uvm.OptionsWCOW, + wc *WCOWConfidentialOptions, + guestConfig *WindowsGuestOptions, + memConfig *MemoryConfig) error { + setStr(&opts.SecurityPolicy, wc.Options.SecurityPolicy) + + if len(opts.SecurityPolicy) > 0 { + if wc.Options != nil { + applyCommonConfidentialWCOW(opts.ConfidentialWCOWOptions, wc.Options) + } + + opts.SecurityPolicyEnabled = true + setBool(&opts.DisableSecureBoot, wc.DisableSecureBoot) + + // overcommit isn't allowed when running in confidential mode and minimum of 2GB memory is required. + // We can change default values here, but if user provided specific values in annotations we should error out. + if memConfig == nil || memConfig.GetMemorySizeInMb() == 0 { + // No memory config provided, set to minimum required. + opts.MemorySizeInMB = 2048 + } + if opts.MemorySizeInMB < 2048 { + return fmt.Errorf("minimum 2048MB of memory is required for confidential pods, got: %d", opts.MemorySizeInMB) + } + + opts.IsolationType = "SecureNestedPaging" + if wc.Options.NoSecurityHardware != nil && *wc.Options.NoSecurityHardware { + opts.IsolationType = "GuestStateOnly" + } + setStr(&opts.IsolationType, wc.IsolationType) + err := oci.HandleWCOWIsolationType(opts.IsolationType, opts) + if err != nil { + return err + } + + if guestConfig == nil || guestConfig.ForwardLogs == nil { + // Disable log forwarding by default for confidential containers. + opts.ForwardLogs = false + } + } + + setBool(&opts.WritableEFI, wc.WritableEfi) + + return nil +} + +// ----------------------------------------------------------------------------- +// Confidential (common) +// ----------------------------------------------------------------------------- + +func applyCommonConfidentialLCOW(opts *uvm.ConfidentialLCOWOptions, c *ConfidentialOptions) { + setStr(&opts.SecurityPolicy, c.SecurityPolicy) + setStr(&opts.SecurityPolicyEnforcer, c.SecurityPolicyEnforcer) + setStr(&opts.UVMReferenceInfoFile, c.UvmReferenceInfoFile) +} + +func applyCommonConfidentialWCOW(opts *uvm.ConfidentialWCOWOptions, c *ConfidentialOptions) { + setStr(&opts.GuestStateFilePath, c.GuestStateFile) + setStr(&opts.SecurityPolicyEnforcer, c.SecurityPolicyEnforcer) + setStr(&opts.UVMReferenceInfoFile, c.UvmReferenceInfoFile) +} + +// Proto adapter: map proto values to hcsschema.RegistryValue. +func registryValuesFromProto(wgo *WindowsGuestOptions) []hcsschema.RegistryValue { + if wgo == nil || len(wgo.AdditionalRegistryKeys) == 0 { + return []hcsschema.RegistryValue{} + } + + out := make([]hcsschema.RegistryValue, 0, len(wgo.AdditionalRegistryKeys)) + for _, pv := range wgo.AdditionalRegistryKeys { + if pv == nil { + continue + } + + var key *hcsschema.RegistryKey + if pv.Key != nil { + key = &hcsschema.RegistryKey{ + Hive: mapProtoHive(pv.Key.Hive), + Name: strings.TrimSpace(pv.Key.Name), + Volatile: pv.Key.Volatile, + } + } + + out = append(out, hcsschema.RegistryValue{ + Key: key, + Name: strings.TrimSpace(pv.Name), + Type_: mapProtoRegValueType(pv.Type), + StringValue: pv.StringValue, + BinaryValue: pv.BinaryValue, + DWordValue: pv.DwordValue, + QWordValue: pv.QwordValue, + CustomType: pv.CustomType, + }) + } + return out +} + +// ----------------------------------------------------------------------------- +// Small utilities to reduce nil-check boilerplate +// ----------------------------------------------------------------------------- + +// Map proto RegistryHive -> hcsschema.RegistryHive. +func mapProtoHive(h RegistryHive) hcsschema.RegistryHive { + switch h { + case RegistryHive_REGISTRY_HIVE_SYSTEM: + return hcsschema.RegistryHive_SYSTEM + case RegistryHive_REGISTRY_HIVE_SOFTWARE: + return hcsschema.RegistryHive_SOFTWARE + case RegistryHive_REGISTRY_HIVE_SECURITY: + return hcsschema.RegistryHive_SECURITY + case RegistryHive_REGISTRY_HIVE_SAM: + return hcsschema.RegistryHive_SAM + default: + return hcsschema.RegistryHive_SYSTEM + } +} + +// Map proto RegistryValueType -> hcsschema.RegistryValueType. +func mapProtoRegValueType(t RegistryValueType) hcsschema.RegistryValueType { + switch t { + case RegistryValueType_REGISTRY_VALUE_TYPE_NONE: + return hcsschema.RegistryValueType_NONE + case RegistryValueType_REGISTRY_VALUE_TYPE_STRING: + return hcsschema.RegistryValueType_STRING + case RegistryValueType_REGISTRY_VALUE_TYPE_EXPANDED_STRING: + return hcsschema.RegistryValueType_EXPANDED_STRING + case RegistryValueType_REGISTRY_VALUE_TYPE_MULTI_STRING: + return hcsschema.RegistryValueType_MULTI_STRING + case RegistryValueType_REGISTRY_VALUE_TYPE_BINARY: + return hcsschema.RegistryValueType_BINARY + case RegistryValueType_REGISTRY_VALUE_TYPE_D_WORD: + return hcsschema.RegistryValueType_D_WORD + case RegistryValueType_REGISTRY_VALUE_TYPE_Q_WORD: + return hcsschema.RegistryValueType_Q_WORD + case RegistryValueType_REGISTRY_VALUE_TYPE_CUSTOM_TYPE: + return hcsschema.RegistryValueType_CUSTOM_TYPE + default: + return hcsschema.RegistryValueType_NONE + } +} + +// setStr sets dst to the value of src if src is non-nil. +func setStr(dst *string, src *string) { + if src != nil { + *dst = *src + } +} + +// setBool sets dst to the value of src if src is non-nil. +func setBool(dst *bool, src *bool) { + if src != nil { + *dst = *src + } +} + +// setU32 sets dst to the value of src if src is non-nil. +func setU32(dst *uint32, src *uint32) { + if src != nil { + *dst = *src + } +} + +// setU64 sets dst to the value of src if src is non-nil. +func setU64(dst *uint64, src *uint64) { + if src != nil { + *dst = *src + } +} + +// copyU32 returns a copy of in. +func copyU32(in []uint32) []uint32 { + out := make([]uint32, len(in)) + copy(out, in) + return out +} + +// copyU64 returns a copy of in. +func copyU64(in []uint64) []uint64 { + out := make([]uint64, len(in)) + copy(out, in) + return out +} diff --git a/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs_test.go b/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs_test.go new file mode 100644 index 0000000000..8e18531f86 --- /dev/null +++ b/cmd/containerd-shim-runhcs-v1/sandboxspec/uvm_specs_test.go @@ -0,0 +1,752 @@ +//go:build windows + +package sandboxspec + +import ( + "context" + "reflect" + "testing" + + "github.com/Microsoft/go-winio/pkg/guid" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/uvm" + + "github.com/containerd/platforms" + "github.com/google/go-cmp/cmp" +) + +func TestBuildUVMOptions(t *testing.T) { + // Common test constants + const ( + id = "test-id" + owner = "test-owner" + ) + validGUID := "00000000-0000-0000-0000-000000000001" + + // Helper to create a base LCOW option set for expectations + baseLCOW := func() *uvm.OptionsLCOW { + return uvm.NewDefaultOptionsLCOW(id, owner) + } + + // Helper to create a base WCOW option set for expectations + baseWCOW := func() *uvm.OptionsWCOW { + return uvm.NewDefaultOptionsWCOW(id, owner) + } + + type testCase struct { + name string + spec *Specs + expectedLCOW *uvm.OptionsLCOW + expectedWCOW *uvm.OptionsWCOW + expectedPlat *platforms.Platform + expectError bool + } + + tests := []testCase{ + // ==================================================================== + // LCOW Tests + // ==================================================================== + { + name: "LCOW_Success_FullMapping", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{ + Architecture: ptr("amd64"), + ProcessorCount: ptr(int32(4)), + }, + MemoryConfig: &MemoryConfig{ + MemorySizeInMb: ptr(uint64(2048)), + }, + StorageConfig: &StorageConfig{ + StorageQosIopsMaximum: ptr(int32(1000)), + }, + ResourcePartitionID: ptr(validGUID), + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{ + KernelDirect: ptr(true), + KernelBootOptions: ptr("debug"), + }, + LinuxGuestOptions: &LinuxGuestOptions{ + DisableTimeSyncService: ptr(true), + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.ProcessorCount = 4 + o.MemorySizeInMB = 2048 + o.StorageQoSIopsMaximum = 1000 + g, _ := guid.FromString(validGUID) + o.ResourcePartitionID = &g + + // LCOW Specifics + o.KernelDirect = true + o.KernelBootOptions = "debug" + o.DisableTimeSyncService = true + o.EnableScratchEncryption = false // default + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + // LCOW Confidential Overrides + // Testing that Confidential options are applied correctly. + { + name: "LCOW_Confidential_Overrides", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("policy-string"), + }, + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.SecurityPolicy = "policy-string" + o.EnableScratchEncryption = true // implicitly set + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // LCOW "Kitchen Sink" + // Testing the interaction of Custom Boot, complex NUMA, Device assignment, + // and Confidential settings simultaneously. + { + name: "LCOW_KitchenSink", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{ + Architecture: ptr("amd64"), + ProcessorCount: ptr(int32(8)), + ProcessorLimit: ptr(int32(90000)), // 90% + ProcessorWeight: ptr(int32(500)), + }, + MemoryConfig: &MemoryConfig{ + MemorySizeInMb: ptr(uint64(4096)), + LowMmioGapInMb: ptr(uint64(128)), + HighMmioBaseInMb: ptr(uint64(1024)), + AllowOvercommit: ptr(false), + }, + NumaConfig: &NUMAConfig{ + MaxProcessorsPerNumaNode: ptr(uint32(4)), + PreferredPhysicalNumaNodes: []uint32{0, 1}, + }, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{ + // Setting a custom path should trigger UpdateBootFilesPath logic + BootFilesPath: ptr(`C:\Custom\Boot`), + PreferredRootFsType: ptr(PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_VHD), + HclEnabled: ptr(true), + }, + LinuxGuestOptions: &LinuxGuestOptions{ + ExtraVsockPorts: []uint32{8080, 9090}, + PolicyBasedRouting: ptr(true), + WritableOverlayDirs: ptr(true), + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("base64-policy-data"), + }, + DmVerityMode: ptr(true), + }, + // Device options with mocked values + LinuxDeviceOptions: &LinuxDeviceOptions{ + VpMemDeviceCount: ptr(uint32(16)), + VpciEnabled: ptr(true), + // Note: Actual device ID parsing depends on 'oci.ParseDevices' logic. + // We assume simple passthrough for the unit test context here. + AssignedDevices: []*Device{ + {ID: "class/8888", IdType: "vpci"}, + }, + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + // CPU & Memory + o.ProcessorCount = 8 + o.ProcessorLimit = 90000 + o.ProcessorWeight = 500 + o.MemorySizeInMB = 4096 + o.LowMMIOGapInMB = 128 + o.HighMMIOBaseInMB = 1024 + o.AllowOvercommit = false + + // NUMA + o.MaxProcessorsPerNumaNode = 4 + o.PreferredPhysicalNumaNodes = []uint32{0, 1} + + // Boot Options (UpdateBootFilesPath logic simulation) + o.BootFilesPath = `C:\Custom\Boot` + // Note: UpdateBootFilesPath in the real code checks for file existence (os.Stat). + // In a unit test environment without those files, it updates the path string + // but might not auto-update RootFSFile unless mocked. + // Based on your provided code, it sets the path string at minimum. + o.PreferredRootFSType = uvm.PreferredRootFSTypeVHD + o.RootFSFile = uvm.VhdFile // VHD type implies this file name + hcl := true + o.HclEnabled = &hcl + + // Guest Options + o.ExtraVSockPorts = []uint32{8080, 9090} + o.PolicyBasedRouting = true + o.WritableOverlayDirs = true + + // Confidential + o.SecurityPolicy = "base64-policy-data" + o.DmVerityMode = true + o.EnableScratchEncryption = true // Side effect of having SecurityPolicy + + // Devices + o.VPMemDeviceCount = 16 + o.VPCIEnabled = true + devs := make([]uvm.VPCIDeviceID, 0) + devs = append(devs, uvm.NewVPCIDeviceID("class", 8888)) + o.AssignedDevices = devs + + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // Logic Test: Logic_LCOW_Overrides Overrides for LCOW + // - FullyPhysicallyBacked == true, then AllowOvercommit=false and VPMemDeviceCount=0 (for LCOW). + // - Check for KernelFile when KernelDirect is false. + // - Validate the PreferredRootFsType mapping. + { + name: "Logic_LCOW_Overrides", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{ + FullyPhysicallyBacked: ptr(true), + // Even if we explicitly ask for overcommit, PhysicallyBacked should win + AllowOvercommit: ptr(true), + }, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxBootOptions: &LinuxBootOptions{ + KernelDirect: ptr(false), + PreferredRootFsType: ptr(PreferredRootFSType_PREFERRED_ROOT_FS_TYPE_INITRD), + }, + LinuxDeviceOptions: &LinuxDeviceOptions{ + // Even if we ask for devices, PhysicallyBacked should force 0 + VpMemDeviceCount: ptr(uint32(50)), + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.FullyPhysicallyBacked = true + o.AllowOvercommit = false // Overridden + o.VPMemDeviceCount = 0 // Overridden + o.KernelDirect = false + o.KernelFile = uvm.KernelFile + o.PreferredRootFSType = uvm.PreferredRootFSTypeInitRd + o.RootFSFile = uvm.InitrdFile + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // Logic Test: LCOW SNP Enforcement (NoSecurityHardware = false) + // This verifies that valid SNP hardware settings FORCE specific overrides, + // ignoring conflicting user inputs (like VpMemDeviceCount). + { + name: "Logic_LCOW_SNP_Hardware_Enforcement", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + // User tries to enable Overcommit, but SNP should force it to false + MemoryConfig: &MemoryConfig{AllowOvercommit: ptr(true)}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxDeviceOptions: &LinuxDeviceOptions{ + // User tries to add VPMem, but SNP (without VHD boot) forces 0 + VpMemDeviceCount: ptr(uint32(10)), + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + GuestStateFile: ptr("abcd"), + SecurityPolicy: ptr("policy-string"), + NoSecurityHardware: ptr(false), // Enforce Hardware rules + }, + DmVerityRootFsVhd: ptr("hello"), + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.SecurityPolicy = "policy-string" + o.EnableScratchEncryption = true + + // --- Forced Overrides by HandleLCOWSecurityPolicyWithNoSecurityHardware --- + o.VPMemDeviceCount = 0 + o.AllowOvercommit = false + o.SecurityPolicyEnabled = true + o.GuestStateFile = uvm.GuestStateFile // uvm.GuestStateFile + o.KernelBootOptions = "" + o.PreferredRootFSType = uvm.PreferredRootFSTypeNA // uvm.PreferredRootFSTypeNA + o.RootFSFile = "" + o.DmVerityRootFsVhd = uvm.DefaultDmVerityRootfsVhd // uvm.DefaultDmVerityRootfsVhd + o.DmVerityMode = true + + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // Logic Test: LCOW SNP Dev Mode (NoSecurityHardware = true) + // This verifies that when NoSecurityHardware is set, we SKIP the enforcement + // logic, allowing "unsafe" configurations like VPMem and Overcommit to persist. + { + name: "Logic_LCOW_SNP_NoSecurityHardware_Skip", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + // These settings should be preserved because we are skipping enforcement + MemoryConfig: &MemoryConfig{AllowOvercommit: ptr(true)}, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{ + LinuxDeviceOptions: &LinuxDeviceOptions{ + VpMemDeviceCount: ptr(uint32(10)), + }, + ConfidentialOptions: &LCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("policy-string"), + NoSecurityHardware: ptr(true), // Skip Enforcement + }, + }, + }, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.SecurityPolicy = "policy-string" + + // --- Values should REMAIN as set by user --- + o.VPMemDeviceCount = 10 + o.AllowOvercommit = true + + // Side effect still happens because policy string exists + o.EnableScratchEncryption = true + + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // ==================================================================== + // WCOW Tests + // ==================================================================== + { + name: "WCOW_Success_FullMapping", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{ + Architecture: ptr("amd64"), + ProcessorCount: ptr(int32(2)), + }, + AdditionalConfig: &AdditionalConfig{ + ConsolePipe: ptr(`\\.\pipe\test`), + }, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{ + NoDirectMap: ptr(true), + }, + WindowsGuestOptions: &WindowsGuestOptions{ + NoInheritHostTimezone: ptr(true), + LogSources: ptr("Microsoft-Windows-HyperV-Guest-Logs"), + }, + }, + }, + }, + }, + }, + expectedWCOW: func() *uvm.OptionsWCOW { + o := baseWCOW() + o.ProcessorCount = 2 + o.ConsolePipe = `\\.\pipe\test` + o.NoDirectMap = true + o.NoInheritHostTimezone = true + o.ForwardLogs = true // By default for non-confidential + o.LogSources = "Microsoft-Windows-HyperV-Guest-Logs" + return o + }(), + expectedPlat: &platforms.Platform{OS: "windows", Architecture: "amd64"}, + }, + { + name: "WCOW_Confidential_Overrides", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("policy"), + }, + IsolationType: ptr("SNP"), // Short for SecureNestedPaging + }, + }, + }, + }, + }, + }, + expectedWCOW: func() *uvm.OptionsWCOW { + o := baseWCOW() + o.SecurityPolicy = "policy" + o.SecurityPolicyEnabled = true + o.MemorySizeInMB = 2048 // Default minimum forced by confidential + o.IsolationType = "SecureNestedPaging" + o.AllowOvercommit = false // Forced by SNP + o.ForwardLogs = false // Default for confidential + return o + }(), + expectedPlat: &platforms.Platform{OS: "windows", Architecture: "amd64"}, + }, + // WCOW "Kitchen Sink" with Registry Complexity + // Testing Registry mapping, complex types, and filtering logic interactions. + { + name: "WCOW_KitchenSink", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{ + FullyPhysicallyBacked: ptr(true), + // Even if we explicitly ask for overcommit, PhysicallyBacked should win + AllowOvercommit: ptr(true), + }, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + WindowsBootOptions: &WindowsBootOptions{ + DisableCompartmentNamespace: ptr(true), + }, + WindowsGuestOptions: &WindowsGuestOptions{ + // We must use registry keys that pass the `ValidateAndFilterRegistryValues` allow-list. + // Allowed: HKLM\Software\... + AdditionalRegistryKeys: []*RegistryValue{ + { + Key: &RegistryKey{ + Hive: RegistryHive_REGISTRY_HIVE_SOFTWARE, + Name: "Software\\ContainerPlat\\Test", + }, + Name: "StringVal", + Type: RegistryValueType_REGISTRY_VALUE_TYPE_STRING, + StringValue: "MyString", + }, + { + Key: &RegistryKey{ + Hive: RegistryHive_REGISTRY_HIVE_SOFTWARE, + Name: "Software\\ContainerPlat\\Test", + }, + Name: "DwordVal", + Type: RegistryValueType_REGISTRY_VALUE_TYPE_D_WORD, + DwordValue: 12345, + }, + }, + }, + }, + }, + }, + }, + }, + expectedWCOW: func() *uvm.OptionsWCOW { + o := baseWCOW() + o.DisableCompartmentNamespace = true + o.AdditionalRegistryKeys = []hcsschema.RegistryValue{ + { + Key: &hcsschema.RegistryKey{Hive: hcsschema.RegistryHive_SOFTWARE, Name: "Software\\ContainerPlat\\Test"}, + Name: "StringVal", + Type_: hcsschema.RegistryValueType_STRING, + StringValue: "MyString", + }, + { + Key: &hcsschema.RegistryKey{Hive: hcsschema.RegistryHive_SOFTWARE, Name: "Software\\ContainerPlat\\Test"}, + Name: "DwordVal", + Type_: hcsschema.RegistryValueType_D_WORD, + DWordValue: 12345, + }, + } + o.FullyPhysicallyBacked = true + o.AllowOvercommit = false // Overridden + return o + }(), + expectedPlat: &platforms.Platform{OS: "windows", Architecture: "amd64"}, + }, + // Logic Test: WCOW Confidential Memory Constraint + // Confidential WCOW requires at least 2048MB. + { + name: "Logic_WCOW_Confidential_LowMemory_Error", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{ + MemorySizeInMb: ptr(uint64(1024)), // Too low + }, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("policy"), + }, + }, + }, + }, + }, + }, + }, + expectError: true, // Should fail validation + }, + // Logic Test: WCOW Isolation Type Shorthands + // Verifying that "VBS" maps to "VirtualizationBasedSecurity" + { + name: "Logic_WCOW_IsolationType", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{ + AllowOvercommit: ptr(true), // Should be overridden + }, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + SecurityPolicy: ptr("policy"), + }, + IsolationType: ptr("VBS"), + }, + }, + }, + }, + }, + }, + expectedWCOW: func() *uvm.OptionsWCOW { + o := baseWCOW() + o.SecurityPolicy = "policy" + o.SecurityPolicyEnabled = true + o.MemorySizeInMB = 2048 + o.IsolationType = "VirtualizationBasedSecurity" // Expanded + o.AllowOvercommit = false + o.ForwardLogs = false + return o + }(), + expectedPlat: &platforms.Platform{OS: "windows", Architecture: "amd64"}, + }, + { + name: "WCOW_Non_Confidential_DoesNotOverride", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + MemoryConfig: &MemoryConfig{}, + Platform: &HypervisorIsolated_Wcow{ + Wcow: &WindowsHyperVOptions{ + ConfidentialOptions: &WCOWConfidentialOptions{ + Options: &ConfidentialOptions{ + GuestStateFile: ptr("abcd"), + }, + DisableSecureBoot: ptr(true), + IsolationType: ptr("SNP"), // Short for SecureNestedPaging + }, + }, + }, + }, + }, + }, + expectedWCOW: func() *uvm.OptionsWCOW { + o := baseWCOW() + return o + }(), + expectedPlat: &platforms.Platform{OS: "windows", Architecture: "amd64"}, + }, + + // ==================================================================== + // Common Config Tests (Registry, HvSocket) + // ==================================================================== + { + name: "Common_HvSocket_ServiceTable", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + AdditionalConfig: &AdditionalConfig{ + AdditionalHypervConfig: map[string]*HvSocketServiceConfig{ + validGUID: { + AllowWildcardBinds: ptr(true), + Disabled: ptr(false), + }, + }, + }, + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{}, + }, + }, + }, + }, + expectedLCOW: func() *uvm.OptionsLCOW { + o := baseLCOW() + o.AdditionalHyperVConfig[validGUID] = hcsschema.HvSocketServiceConfig{ + AllowWildcardBinds: true, + Disabled: false, + } + return o + }(), + expectedPlat: &platforms.Platform{OS: "linux", Architecture: "amd64"}, + }, + + // ==================================================================== + // Error Cases + // ==================================================================== + { + name: "Error_NilSpec", + spec: nil, + expectError: true, + }, + { + name: "Error_ProcessIsolation", + spec: &Specs{ + IsolationLevel: &Specs_Process{}, + }, + expectError: true, + }, + { + name: "Error_MissingHypervisor", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: nil, + }, + }, + expectError: true, + }, + { + name: "Error_MissingPlatform_LCOW", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + Platform: &HypervisorIsolated_Lcow{ + Lcow: nil, + }, + }, + }, + }, + expectError: true, + }, + { + name: "Error_MissingPlatform_WCOW", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + Platform: &HypervisorIsolated_Wcow{ + Wcow: nil, + }, + }, + }, + }, + expectError: true, + }, + { + name: "Error_Invalid_ResourcePartition_GUID", + spec: &Specs{ + IsolationLevel: &Specs_Hypervisor{ + Hypervisor: &HypervisorIsolated{ + CpuConfig: &CPUConfig{Architecture: ptr("amd64")}, + ResourcePartitionID: ptr("not-a-guid"), + Platform: &HypervisorIsolated_Lcow{ + Lcow: &LinuxHyperVOptions{}, + }, + }, + }, + }, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotLCOW, gotWCOW, gotPlat, err := BuildUVMOptions(context.Background(), tt.spec, id, owner) + + if tt.expectError { + if err == nil { + t.Error("Expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // Validate Platform + if !reflect.DeepEqual(gotPlat, tt.expectedPlat) { + t.Errorf("Platform mismatch.\nGot: %+v\nWant: %+v", gotPlat, tt.expectedPlat) + } + + opts := cmp.Options{ + cmp.AllowUnexported(uvm.VPCIDeviceID{}), + } + + if tt.expectedLCOW != nil { + if gotLCOW == nil { + t.Fatal("Expected LCOW options, got nil") + } + + gotLCOW.OutputHandlerCreator = nil + tt.expectedLCOW.OutputHandlerCreator = nil + + if diff := cmp.Diff(tt.expectedLCOW, gotLCOW, opts); diff != "" { + t.Errorf("LCOW Options mismatch (-want +got):\n%s", diff) + } + } else if tt.expectedWCOW != nil { + if gotWCOW == nil { + t.Fatal("Expected WCOW options, got nil") + } + + gotWCOW.OutputHandlerCreator = nil + tt.expectedWCOW.OutputHandlerCreator = nil + + if diff := cmp.Diff(tt.expectedWCOW, gotWCOW, opts); diff != "" { + t.Errorf("WCOW Options mismatch (-want +got):\n%s", diff) + } + } else { + t.Fatal("Test case did not specify expected LCOW or WCOW output") + } + }) + } +} diff --git a/cmd/containerd-shim-runhcs-v1/service_internal.go b/cmd/containerd-shim-runhcs-v1/service_internal.go index 53821191b7..a50bb12224 100644 --- a/cmd/containerd-shim-runhcs-v1/service_internal.go +++ b/cmd/containerd-shim-runhcs-v1/service_internal.go @@ -107,7 +107,7 @@ func (s *service) createInternal(ctx context.Context, req *task.CreateTaskReques spec = oci.UpdateSpecFromOptions(spec, shimOpts) // expand annotations after defaults have been loaded in from options - err = oci.ProcessAnnotations(ctx, &spec) + err = oci.ProcessAnnotations(ctx, spec.Annotations) // since annotation expansion is used to toggle security features // raise it rather than suppress and move on if err != nil { diff --git a/internal/oci/annotations.go b/internal/oci/annotations.go index 7463bc9dfe..e0d64a6129 100644 --- a/internal/oci/annotations.go +++ b/internal/oci/annotations.go @@ -24,7 +24,7 @@ var ErrAnnotationExpansionConflict = errors.New("annotation expansion conflict") var ErrGenericAnnotationConflict = errors.New("specified annotations conflict") // ProcessAnnotations expands annotations into their corresponding annotation groups. -func ProcessAnnotations(ctx context.Context, s *specs.Spec) error { +func ProcessAnnotations(ctx context.Context, specAnnotations map[string]string) error { // Named `Process` and not `Expand` since this function may be expanded (pun intended) to // deal with other annotation issues and validation. @@ -36,11 +36,11 @@ func ProcessAnnotations(ctx context.Context, s *specs.Spec) error { var errs []error for key, exps := range annotations.AnnotationExpansionMap() { // check if annotation is present - if val, ok := s.Annotations[key]; ok { + if val, ok := specAnnotations[key]; ok { // ideally, some normalization would occur here (ie, "True" -> "true") // but strings may be case-sensitive for _, k := range exps { - if v, ok := s.Annotations[k]; ok && val != v { + if v, ok := specAnnotations[k]; ok && val != v { err := fmt.Errorf("%w: %q = %q and %q = %q", ErrAnnotationExpansionConflict, key, val, k, v) errs = append(errs, err) log.G(ctx).WithFields(logrus.Fields{ @@ -51,26 +51,26 @@ func ProcessAnnotations(ctx context.Context, s *specs.Spec) error { }).WithError(err).Warning("annotation expansion would overwrite conflicting value") continue } - s.Annotations[k] = val + specAnnotations[k] = val } } } // validate host process containers annotations are not conflicting - disableHPC := ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableHostProcessContainer, false) - enableHPC := ParseAnnotationsBool(ctx, s.Annotations, annotations.HostProcessContainer, false) + disableHPC := ParseAnnotationsBool(ctx, specAnnotations, annotations.DisableHostProcessContainer, false) + enableHPC := ParseAnnotationsBool(ctx, specAnnotations, annotations.HostProcessContainer, false) if disableHPC && enableHPC { err := fmt.Errorf("%w: host process container annotations %q = %q and %q = %q", ErrGenericAnnotationConflict, - annotations.DisableHostProcessContainer, s.Annotations[annotations.DisableHostProcessContainer], - annotations.HostProcessContainer, s.Annotations[annotations.HostProcessContainer]) + annotations.DisableHostProcessContainer, specAnnotations[annotations.DisableHostProcessContainer], + annotations.HostProcessContainer, specAnnotations[annotations.HostProcessContainer]) errs = append(errs, err) log.G(ctx).WithFields(logrus.Fields{ logfields.OCIAnnotation: annotations.DisableHostProcessContainer, - logfields.Value: s.Annotations[annotations.DisableHostProcessContainer], + logfields.Value: specAnnotations[annotations.DisableHostProcessContainer], logfields.OCIAnnotation + "-conflict": annotations.HostProcessContainer, - logfields.Value + "-conflict": s.Annotations[annotations.HostProcessContainer], + logfields.Value + "-conflict": specAnnotations[annotations.HostProcessContainer], }).WithError(err).Warning("Host process container and disable host process container cannot both be true") } @@ -86,10 +86,10 @@ func ParseAnnotationsDisableGMSA(ctx context.Context, s *specs.Spec) bool { return ParseAnnotationsBool(ctx, s.Annotations, annotations.WCOWDisableGMSA, false) } -// parseAdditionalRegistryValues extracts the additional registry values to set from annotations. +// ParseAdditionalRegistryValues extracts the additional registry values to set from annotations. // // Like the [parseAnnotation*] functions, this logs errors but does not return them. -func parseAdditionalRegistryValues(ctx context.Context, a map[string]string) []hcsschema.RegistryValue { +func ParseAdditionalRegistryValues(ctx context.Context, a map[string]string) []hcsschema.RegistryValue { // rather than have users deal with nil vs []hcsschema.RegistryValue as returns, always // return the latter. // this is mostly to make testing easier, since its awkward to have to differentiate between @@ -108,12 +108,16 @@ func parseAdditionalRegistryValues(ctx context.Context, a map[string]string) []h } // basic error checking: warn about and delete invalid registry keys - rvs := make([]hcsschema.RegistryValue, 0, len(t)) - for _, rv := range t { + return ValidateAndFilterRegistryValues(ctx, t) +} + +func ValidateAndFilterRegistryValues(ctx context.Context, input []hcsschema.RegistryValue) []hcsschema.RegistryValue { + rvs := make([]hcsschema.RegistryValue, 0, len(input)) + + for _, rv := range input { entry := log.G(ctx).WithFields(logrus.Fields{ - logfields.OCIAnnotation: k, - logfields.Value: v, - "registry-value": log.Format(ctx, rv), + logfields.Value: log.Format(ctx, rv), + "registry-value": log.Format(ctx, rv), }) if rv.Key == nil { @@ -157,7 +161,10 @@ func parseAdditionalRegistryValues(ctx context.Context, a map[string]string) []h // multiple values are set b2i := map[bool]int{true: 1} // hack to convert bool to int - if (b2i[rv.StringValue != ""] + b2i[rv.BinaryValue != ""] + b2i[rv.DWordValue != 0] + b2i[rv.QWordValue != 0]) > 1 { + if (b2i[rv.StringValue != ""] + + b2i[rv.BinaryValue != ""] + + b2i[rv.DWordValue != 0] + + b2i[rv.QWordValue != 0]) > 1 { entry.Warning("multiple values set") continue } @@ -204,10 +211,10 @@ func parseAdditionalRegistryValues(ctx context.Context, a map[string]string) []h return slices.Clip(rvs) } -// parseHVSocketServiceTable extracts any additional Hyper-V socket service configurations from annotations. +// ParseHVSocketServiceTable extracts any additional Hyper-V socket service configurations from annotations. // // Like the [parseAnnotation*] functions, this logs errors but does not return them. -func parseHVSocketServiceTable(ctx context.Context, a map[string]string) map[string]hcsschema.HvSocketServiceConfig { +func ParseHVSocketServiceTable(ctx context.Context, a map[string]string) map[string]hcsschema.HvSocketServiceConfig { sc := make(map[string]hcsschema.HvSocketServiceConfig) // TODO(go1.23) use range over functions to implement a functional `filter | map $ a` for k, v := range a { diff --git a/internal/oci/annotations_test.go b/internal/oci/annotations_test.go index eee585fa7b..2879f9f196 100644 --- a/internal/oci/annotations_test.go +++ b/internal/oci/annotations_test.go @@ -117,11 +117,10 @@ func TestProccessAnnotations_HostProcessContainer(t *testing.T) { for _, tt := range testAnnotations { t.Run(tt.name, func(t *testing.T) { spec := specs.Spec{ - Windows: &specs.Windows{}, Annotations: tt.an, } - err := ProcessAnnotations(ctx, &spec) + err := ProcessAnnotations(ctx, spec.Annotations) if err != nil && len(tt.errs) == 0 { t.Fatalf("ProcessAnnotations should have succeeded, instead got %v", err) } @@ -181,7 +180,7 @@ func TestProccessAnnotations_Expansion(t *testing.T) { annotations.DisableUnsafeOperations: v, } - err := ProcessAnnotations(ctx, &tt.spec) + err := ProcessAnnotations(ctx, tt.spec.Annotations) if err != nil { subtest.Fatalf("could not update spec from options: %v", err) } @@ -206,7 +205,7 @@ func TestProccessAnnotations_Expansion(t *testing.T) { annotations.DisableUnsafeOperations, annotations.DisableWritableFileShares) - err := ProcessAnnotations(ctx, &tt.spec) + err := ProcessAnnotations(ctx, tt.spec.Annotations) if !errors.Is(err, ErrAnnotationExpansionConflict) { t.Fatalf("UpdateSpecFromOptions should have failed with %q, actual was %v", errExp, err) } @@ -348,7 +347,7 @@ func TestParseAdditionalRegistryValues(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Logf("registry values:\n%s", tt.give) v := strings.ReplaceAll(tt.give, "\n", "") - rvs := parseAdditionalRegistryValues(ctx, map[string]string{ + rvs := ParseAdditionalRegistryValues(ctx, map[string]string{ "some-random-annotation": "random", "not-microsoft.virtualmachine.wcow.additional-reg-keys": "this is fake", iannotations.AdditionalRegistryValues: v, @@ -460,7 +459,7 @@ func TestParseHVSocketServiceTable(t *testing.T) { maps.Copy(annots, tt.give) t.Logf("annotations:\n%v", annots) - rvs := parseHVSocketServiceTable(ctx, annots) + rvs := ParseHVSocketServiceTable(ctx, annots) t.Logf("got %v", rvs) want := tt.want if want == nil { diff --git a/internal/oci/uvm.go b/internal/oci/uvm.go index 1c5f32c55f..0ea9e056f2 100644 --- a/internal/oci/uvm.go +++ b/internal/oci/uvm.go @@ -198,6 +198,15 @@ func handleLCOWSecurityPolicy(ctx context.Context, a map[string]string, lopts *u // this is not a security issue as the attestation will fail without a genuine report noSecurityHardware := ParseAnnotationsBool(ctx, a, annotations.NoSecurityHardware, false) + HandleLCOWSecurityPolicyWithNoSecurityHardware(noSecurityHardware, lopts) + + if len(lopts.SecurityPolicy) > 0 { + // will only be false if explicitly set false by the annotation. We will otherwise default to true when there is a security policy + lopts.EnableScratchEncryption = ParseAnnotationsBool(ctx, a, annotations.LCOWEncryptedScratchDisk, true) + } +} + +func HandleLCOWSecurityPolicyWithNoSecurityHardware(noSecurityHardware bool, lopts *uvm.OptionsLCOW) { // if there is a security policy (and SNP) we currently boot in a way that doesn't support any boot options // this might change if the building of the vmgs file were to be done on demand but that is likely // much slower and noy very useful. We do respect the filename of the vmgs file so if it is necessary to @@ -222,11 +231,6 @@ func handleLCOWSecurityPolicy(ctx context.Context, a map[string]string, lopts *u lopts.DmVerityRootFsVhd = uvm.DefaultDmVerityRootfsVhd lopts.DmVerityMode = true } - - if len(lopts.SecurityPolicy) > 0 { - // will only be false if explicitly set false by the annotation. We will otherwise default to true when there is a security policy - lopts.EnableScratchEncryption = ParseAnnotationsBool(ctx, a, annotations.LCOWEncryptedScratchDisk, true) - } } // handleWCOWSecurityPolicy handles parsing confidential pods related options and setting @@ -253,15 +257,18 @@ func handleWCOWSecurityPolicy(ctx context.Context, a map[string]string, wopts *u if noSecurityHardware := ParseAnnotationsBool(ctx, a, annotations.NoSecurityHardware, false); noSecurityHardware { wopts.IsolationType = "GuestStateOnly" } - if err := handleWCOWIsolationType(ctx, a, wopts); err != nil { + + if err := HandleWCOWIsolationType( + ParseAnnotationsString(a, annotations.WCOWIsolationType, wopts.IsolationType), + wopts, + ); err != nil { return err } return nil } -func handleWCOWIsolationType(ctx context.Context, a map[string]string, wopts *uvm.OptionsWCOW) error { - isolationType := ParseAnnotationsString(a, annotations.WCOWIsolationType, wopts.IsolationType) +func HandleWCOWIsolationType(isolationType string, wopts *uvm.OptionsWCOW) error { switch isolationType { case "SecureNestedPaging", "SNP": // Allow VBS & SNP shorthands wopts.IsolationType = "SecureNestedPaging" @@ -279,12 +286,22 @@ func handleWCOWIsolationType(ctx context.Context, a map[string]string, wopts *uv return nil } -func parseDevices(ctx context.Context, specWindows *specs.Windows) []uvm.VPCIDeviceID { +func parseDevicesFromSpec(ctx context.Context, specWindows *specs.Windows) []uvm.VPCIDeviceID { if specWindows == nil || specWindows.Devices == nil { return nil } - extraDevices := []uvm.VPCIDeviceID{} - for _, d := range specWindows.Devices { + + extraDevices := ParseDevices(ctx, specWindows.Devices) + + // nil out the devices on the spec so that they aren't re-added to the + // pause container. + specWindows.Devices = nil + return extraDevices +} + +func ParseDevices(ctx context.Context, windowsDevices []specs.WindowsDevice) []uvm.VPCIDeviceID { + var extraDevices []uvm.VPCIDeviceID + for _, d := range windowsDevices { pciID, index := devices.GetDeviceInfoFromPath(d.ID) if uvm.IsValidDeviceType(d.IDType) { key := uvm.NewVPCIDeviceID(pciID, index) @@ -295,9 +312,6 @@ func parseDevices(ctx context.Context, specWindows *specs.Windows) []uvm.VPCIDev }).Warnf("device type %s invalid, skipping", d.IDType) } } - // nil out the devices on the spec so that they aren't re-added to the - // pause container. - specWindows.Devices = nil return extraDevices } @@ -333,7 +347,7 @@ func specToUVMCreateOptionsCommon(ctx context.Context, opts *uvm.Options, s *spe opts.NumaMemoryBlocksCounts = ParseAnnotationCommaSeparatedUint64(ctx, s.Annotations, annotations.NumaCountOfMemoryBlocks, opts.NumaMemoryBlocksCounts) - maps.Copy(opts.AdditionalHyperVConfig, parseHVSocketServiceTable(ctx, s.Annotations)) + maps.Copy(opts.AdditionalHyperVConfig, ParseHVSocketServiceTable(ctx, s.Annotations)) // parse error yielding annotations var err error @@ -396,7 +410,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) ( lopts.HclEnabled = ParseAnnotationsNullableBool(ctx, s.Annotations, annotations.LCOWHclEnabled) // Add devices on the spec to the UVM's options - lopts.AssignedDevices = parseDevices(ctx, s.Windows) + lopts.AssignedDevices = parseDevicesFromSpec(ctx, s.Windows) lopts.PolicyBasedRouting = ParseAnnotationsBool(ctx, s.Annotations, iannotations.NetworkingPolicyBasedRouting, lopts.PolicyBasedRouting) return lopts, nil } else if IsWCOW(s) { @@ -408,7 +422,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) ( wopts.DisableCompartmentNamespace = ParseAnnotationsBool(ctx, s.Annotations, annotations.DisableCompartmentNamespace, wopts.DisableCompartmentNamespace) wopts.NoDirectMap = ParseAnnotationsBool(ctx, s.Annotations, annotations.VSMBNoDirectMap, wopts.NoDirectMap) wopts.NoInheritHostTimezone = ParseAnnotationsBool(ctx, s.Annotations, annotations.NoInheritHostTimezone, wopts.NoInheritHostTimezone) - wopts.AdditionalRegistryKeys = append(wopts.AdditionalRegistryKeys, parseAdditionalRegistryValues(ctx, s.Annotations)...) + wopts.AdditionalRegistryKeys = append(wopts.AdditionalRegistryKeys, ParseAdditionalRegistryValues(ctx, s.Annotations)...) handleAnnotationFullyPhysicallyBacked(ctx, s.Annotations, wopts) // Writable EFI is valid for both confidential and regular Hyper-V isolated WCOW.