diff --git a/internal/guest/prot/protocol.go b/internal/guest/prot/protocol.go index 356b29fce3..acec8a7806 100644 --- a/internal/guest/prot/protocol.go +++ b/internal/guest/prot/protocol.go @@ -773,6 +773,7 @@ type MappedVirtualDiskV2 struct { Lun uint8 `json:",omitempty"` Controller uint8 `json:",omitempty"` ReadOnly bool `json:",omitempty"` + Encrypted bool `json:",omitempty"` Options []string `json:",omitempty"` VerityInfo *DeviceVerityInfo `json:",omitempty"` } diff --git a/internal/guest/runtime/hcsv2/uvm.go b/internal/guest/runtime/hcsv2/uvm.go index a3486dae78..9d9af86ac9 100644 --- a/internal/guest/runtime/hcsv2/uvm.go +++ b/internal/guest/runtime/hcsv2/uvm.go @@ -432,12 +432,12 @@ func modifyMappedVirtualDisk(ctx context.Context, rt prot.ModifyRequestType, mvd mountCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() if mvd.MountPath != "" { - return scsi.Mount(mountCtx, mvd.Controller, mvd.Lun, mvd.MountPath, mvd.ReadOnly, false, mvd.Options, mvd.VerityInfo, securityPolicy) + return scsi.Mount(mountCtx, mvd.Controller, mvd.Lun, mvd.MountPath, mvd.ReadOnly, mvd.Encrypted, mvd.Options, mvd.VerityInfo, securityPolicy) } return nil case prot.MreqtRemove: if mvd.MountPath != "" { - if err := scsi.Unmount(ctx, mvd.Controller, mvd.Lun, mvd.MountPath, false); err != nil { + if err := scsi.Unmount(ctx, mvd.Controller, mvd.Lun, mvd.MountPath, mvd.Encrypted); err != nil { return err } } diff --git a/internal/guestrequest/types.go b/internal/guestrequest/types.go index 5e1dd51caf..6d81dc11c8 100644 --- a/internal/guestrequest/types.go +++ b/internal/guestrequest/types.go @@ -37,6 +37,7 @@ type LCOWMappedVirtualDisk struct { Lun uint8 `json:"Lun,omitempty"` Controller uint8 `json:"Controller,omitempty"` ReadOnly bool `json:"ReadOnly,omitempty"` + Encrypted bool `json:"Encrypted,omitempty"` Options []string `json:"Options,omitempty"` VerityInfo *DeviceVerityInfo `json:"VerityInfo,omitempty"` } diff --git a/internal/hcsoci/resources_lcow.go b/internal/hcsoci/resources_lcow.go index c01a1c18f6..a11f22ab83 100644 --- a/internal/hcsoci/resources_lcow.go +++ b/internal/hcsoci/resources_lcow.go @@ -108,7 +108,15 @@ func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r * // if the scsi device is already attached then we take the uvm path that the function below returns // that is where it was previously mounted in UVM - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, hostPath, uvmPathForShare, readOnly, mount.Options, uvm.VMAccessTypeIndividual) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + hostPath, + uvmPathForShare, + readOnly, + false, + mount.Options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount) } @@ -188,7 +196,15 @@ func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r * // must use scsi here since DDA'ing a hyper-v pci device is not supported on VMs that have ANY virtual memory // gpuvhd must be granted VM Group access. options := []string{"ro"} - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, gpuSupportVhdPath, uvm.LCOWNvidiaMountPath, true, options, uvm.VMAccessTypeNoop) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + gpuSupportVhdPath, + uvm.LCOWNvidiaMountPath, + true, + false, + options, + uvm.VMAccessTypeNoop, + ) if err != nil { return errors.Wrapf(err, "failed to add scsi device %s in the UVM %s at %s", gpuSupportVhdPath, coi.HostingSystem.ID(), uvm.LCOWNvidiaMountPath) } diff --git a/internal/hcsoci/resources_wcow.go b/internal/hcsoci/resources_wcow.go index ef7c8c1373..84240406c3 100644 --- a/internal/hcsoci/resources_wcow.go +++ b/internal/hcsoci/resources_wcow.go @@ -159,7 +159,15 @@ func setupMounts(ctx context.Context, coi *createOptionsInternal, r *resources.R r.Add(scsiMount) } else if mount.Type == "virtual-disk" { l.Debug("hcsshim::allocateWindowsResources Hot-adding SCSI virtual disk for OCI mount") - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, mount.Source, uvmPath, readOnly, mount.Options, uvm.VMAccessTypeIndividual) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + mount.Source, + uvmPath, + readOnly, + false, + mount.Options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount) } diff --git a/internal/layers/layers.go b/internal/layers/layers.go index 146f9accf2..0cf06b92d7 100644 --- a/internal/layers/layers.go +++ b/internal/layers/layers.go @@ -216,7 +216,15 @@ func MountContainerLayers(ctx context.Context, containerID string, layerFolders log.G(ctx).WithField("hostPath", hostPath).Debug("mounting scratch VHD") var options []string - scsiMount, err := vm.AddSCSI(ctx, hostPath, containerScratchPathInUVM, false, options, uvm.VMAccessTypeIndividual) + scsiMount, err := vm.AddSCSI( + ctx, + hostPath, + containerScratchPathInUVM, + false, + vm.ScratchEncryptionEnabled(), + options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return "", fmt.Errorf("failed to add SCSI scratch VHD: %s", err) } @@ -280,7 +288,7 @@ func addLCOWLayer(ctx context.Context, vm *uvm.UtilityVM, layerPath string) (uvm options := []string{"ro"} uvmPath = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, vm.UVMMountCounter()) - sm, err := vm.AddSCSI(ctx, layerPath, uvmPath, true, options, uvm.VMAccessTypeNoop) + sm, err := vm.AddSCSI(ctx, layerPath, uvmPath, true, false, options, uvm.VMAccessTypeNoop) if err != nil { return "", fmt.Errorf("failed to add SCSI layer: %s", err) } diff --git a/internal/lcow/scratch.go b/internal/lcow/scratch.go index 12884b4745..ae385a1c1b 100644 --- a/internal/lcow/scratch.go +++ b/internal/lcow/scratch.go @@ -67,7 +67,15 @@ func CreateScratch(ctx context.Context, lcowUVM *uvm.UtilityVM, destFile string, } var options []string - scsi, err := lcowUVM.AddSCSI(ctx, destFile, "", false, options, uvm.VMAccessTypeIndividual) // No destination as not formatted + scsi, err := lcowUVM.AddSCSI( + ctx, + destFile, + "", // No destination as not formatted + false, + lcowUVM.ScratchEncryptionEnabled(), + options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return err } diff --git a/internal/oci/annotations.go b/internal/oci/annotations.go index d56611162a..bff3740512 100644 --- a/internal/oci/annotations.go +++ b/internal/oci/annotations.go @@ -214,6 +214,10 @@ const ( // when setting up ncproxy and computeagent AnnotationNcproxyContainerID = "io.microsoft.network.ncproxy.containerid" + // AnnotationEncryptedScratchDisk indicates whether or not the container scratch disks + // should be encrypted or not + AnnotationEncryptedScratchDisk = "io.microsoft.virtualmachine.storage.scratch.encrypted" + // AnnotationSecurityPolicy is used to specify a security policy for opengcs to enforce AnnotationSecurityPolicy = "io.microsoft.virtualmachine.lcow.securitypolicy" ) diff --git a/internal/oci/uvm.go b/internal/oci/uvm.go index 380795094c..264f6a1a6d 100644 --- a/internal/oci/uvm.go +++ b/internal/oci/uvm.go @@ -329,6 +329,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) ( lopts.BootFilesPath = parseAnnotationsString(s.Annotations, AnnotationBootFilesRootPath, lopts.BootFilesPath) lopts.CPUGroupID = parseAnnotationsString(s.Annotations, AnnotationCPUGroupID, lopts.CPUGroupID) lopts.NetworkConfigProxy = parseAnnotationsString(s.Annotations, AnnotationNetworkConfigProxy, lopts.NetworkConfigProxy) + lopts.EnableScratchEncryption = parseAnnotationsBool(ctx, s.Annotations, AnnotationEncryptedScratchDisk, lopts.EnableScratchEncryption) lopts.SecurityPolicy = parseAnnotationsString(s.Annotations, AnnotationSecurityPolicy, lopts.SecurityPolicy) lopts.KernelBootOptions = parseAnnotationsString(s.Annotations, AnnotationKernelBootOptions, lopts.KernelBootOptions) diff --git a/internal/uvm/create_lcow.go b/internal/uvm/create_lcow.go index 380cdccc84..5fb631cb6e 100644 --- a/internal/uvm/create_lcow.go +++ b/internal/uvm/create_lcow.go @@ -56,26 +56,27 @@ const ( type OptionsLCOW struct { *Options - BootFilesPath string // Folder in which kernel and root file system reside. Defaults to \Program Files\Linux Containers - KernelFile string // Filename under `BootFilesPath` for the kernel. Defaults to `kernel` - KernelDirect bool // Skip UEFI and boot directly to `kernel` - RootFSFile string // Filename under `BootFilesPath` for the UVMs root file system. Defaults to `InitrdFile` - KernelBootOptions string // Additional boot options for the kernel - EnableGraphicsConsole bool // If true, enable a graphics console for the utility VM - ConsolePipe string // The named pipe path to use for the serial console. eg \\.\pipe\vmpipe - SCSIControllerCount uint32 // The number of SCSI controllers. Defaults to 1. Currently we only support 0 or 1. - UseGuestConnection bool // Whether the HCS should connect to the UVM's GCS. Defaults to true - ExecCommandLine string // The command line to exec from init. Defaults to GCS - ForwardStdout bool // Whether stdout will be forwarded from the executed program. Defaults to false - ForwardStderr bool // Whether stderr will be forwarded from the executed program. Defaults to true - OutputHandler OutputHandler `json:"-"` // Controls how output received over HVSocket from the UVM is handled. Defaults to parsing output as logrus messages - VPMemDeviceCount uint32 // Number of VPMem devices. Defaults to `DefaultVPMEMCount`. Limit at 128. If booting UVM from VHD, device 0 is taken. - VPMemSizeBytes uint64 // Size of the VPMem devices. Defaults to `DefaultVPMemSizeBytes`. - VPMemNoMultiMapping bool // Disables LCOW layer multi mapping - PreferredRootFSType PreferredRootFSType // If `KernelFile` is `InitrdFile` use `PreferredRootFSTypeInitRd`. If `KernelFile` is `VhdFile` use `PreferredRootFSTypeVHD` - EnableColdDiscardHint bool // Whether the HCS should use cold discard hints. Defaults to false - VPCIEnabled bool // Whether the kernel should enable pci - SecurityPolicy string // Optional security policy + BootFilesPath string // Folder in which kernel and root file system reside. Defaults to \Program Files\Linux Containers + KernelFile string // Filename under `BootFilesPath` for the kernel. Defaults to `kernel` + KernelDirect bool // Skip UEFI and boot directly to `kernel` + RootFSFile string // Filename under `BootFilesPath` for the UVMs root file system. Defaults to `InitrdFile` + KernelBootOptions string // Additional boot options for the kernel + EnableGraphicsConsole bool // If true, enable a graphics console for the utility VM + ConsolePipe string // The named pipe path to use for the serial console. eg \\.\pipe\vmpipe + SCSIControllerCount uint32 // The number of SCSI controllers. Defaults to 1. Currently we only support 0 or 1. + UseGuestConnection bool // Whether the HCS should connect to the UVM's GCS. Defaults to true + ExecCommandLine string // The command line to exec from init. Defaults to GCS + ForwardStdout bool // Whether stdout will be forwarded from the executed program. Defaults to false + ForwardStderr bool // Whether stderr will be forwarded from the executed program. Defaults to true + OutputHandler OutputHandler `json:"-"` // Controls how output received over HVSocket from the UVM is handled. Defaults to parsing output as logrus messages + VPMemDeviceCount uint32 // Number of VPMem devices. Defaults to `DefaultVPMEMCount`. Limit at 128. If booting UVM from VHD, device 0 is taken. + VPMemSizeBytes uint64 // Size of the VPMem devices. Defaults to `DefaultVPMemSizeBytes`. + VPMemNoMultiMapping bool // Disables LCOW layer multi mapping + PreferredRootFSType PreferredRootFSType // If `KernelFile` is `InitrdFile` use `PreferredRootFSTypeInitRd`. If `KernelFile` is `VhdFile` use `PreferredRootFSTypeVHD` + EnableColdDiscardHint bool // Whether the HCS should use cold discard hints. Defaults to false + VPCIEnabled bool // Whether the kernel should enable pci + EnableScratchEncryption bool // Whether the scratch should be encrypted + SecurityPolicy string // Optional security policy } // defaultLCOWOSBootFilesPath returns the default path used to locate the LCOW @@ -101,27 +102,28 @@ func NewDefaultOptionsLCOW(id, owner string) *OptionsLCOW { // Use KernelDirect boot by default on all builds that support it. kernelDirectSupported := osversion.Build() >= 18286 opts := &OptionsLCOW{ - Options: newDefaultOptions(id, owner), - BootFilesPath: defaultLCOWOSBootFilesPath(), - KernelFile: KernelFile, - KernelDirect: kernelDirectSupported, - RootFSFile: InitrdFile, - KernelBootOptions: "", - EnableGraphicsConsole: false, - ConsolePipe: "", - SCSIControllerCount: 1, - UseGuestConnection: true, - ExecCommandLine: fmt.Sprintf("/bin/gcs -v4 -log-format json -loglevel %s", logrus.StandardLogger().Level.String()), - ForwardStdout: false, - ForwardStderr: true, - OutputHandler: parseLogrus(id), - VPMemDeviceCount: DefaultVPMEMCount, - VPMemSizeBytes: DefaultVPMemSizeBytes, - VPMemNoMultiMapping: osversion.Get().Build < osversion.V19H1, - PreferredRootFSType: PreferredRootFSTypeInitRd, - EnableColdDiscardHint: false, - VPCIEnabled: false, - SecurityPolicy: "", + Options: newDefaultOptions(id, owner), + BootFilesPath: defaultLCOWOSBootFilesPath(), + KernelFile: KernelFile, + KernelDirect: kernelDirectSupported, + RootFSFile: InitrdFile, + KernelBootOptions: "", + EnableGraphicsConsole: false, + ConsolePipe: "", + SCSIControllerCount: 1, + UseGuestConnection: true, + ExecCommandLine: fmt.Sprintf("/bin/gcs -v4 -log-format json -loglevel %s", logrus.StandardLogger().Level.String()), + ForwardStdout: false, + ForwardStderr: true, + OutputHandler: parseLogrus(id), + VPMemDeviceCount: DefaultVPMEMCount, + VPMemSizeBytes: DefaultVPMemSizeBytes, + VPMemNoMultiMapping: osversion.Get().Build < osversion.V19H1, + PreferredRootFSType: PreferredRootFSTypeInitRd, + EnableColdDiscardHint: false, + VPCIEnabled: false, + EnableScratchEncryption: false, + SecurityPolicy: "", } if _, err := os.Stat(filepath.Join(opts.BootFilesPath, VhdFile)); err == nil { @@ -176,6 +178,7 @@ func CreateLCOW(ctx context.Context, opts *OptionsLCOW) (_ *UtilityVM, err error devicesPhysicallyBacked: opts.FullyPhysicallyBacked, createOpts: opts, vpmemMultiMapping: !opts.VPMemNoMultiMapping, + encryptScratch: opts.EnableScratchEncryption, } defer func() { diff --git a/internal/uvm/create_wcow.go b/internal/uvm/create_wcow.go index b00b0feee3..1bd15d203e 100644 --- a/internal/uvm/create_wcow.go +++ b/internal/uvm/create_wcow.go @@ -296,6 +296,7 @@ func CreateWCOW(ctx context.Context, opts *OptionsWCOW) (_ *UtilityVM, err error 1, 0, 0, + false, false) } else { doc.VirtualMachine.RestoreState = &hcsschema.RestoreState{} diff --git a/internal/uvm/scsi.go b/internal/uvm/scsi.go index 5d891a2e2b..49c4b210a2 100644 --- a/internal/uvm/scsi.go +++ b/internal/uvm/scsi.go @@ -77,6 +77,8 @@ type SCSIMount struct { // read-only layers. As RO layers are shared, we perform ref-counting. isLayer bool refCount uint32 + // specifies if this is an encrypted VHD + encrypted bool // specifies if this is a readonly layer readOnly bool // "VirtualDisk" or "PassThru" or "ExtensibleVirtualDisk" disk attachment type. @@ -102,6 +104,8 @@ type addSCSIRequest struct { // attachments, `PassThru` for physical disk and `ExtensibleVirtualDisk` for // Extensible virtual disks. attachmentType string + // indicates if the VHD is encrypted + encrypted bool // indicates if the attachment should be added read only. readOnly bool // guestOptions is a slice that contains optional information to pass to the guest @@ -133,7 +137,18 @@ func (sm *SCSIMount) logFormat() logrus.Fields { } } -func newSCSIMount(uvm *UtilityVM, hostPath, uvmPath, attachmentType, evdType string, refCount uint32, controller int, lun int32, readOnly bool) *SCSIMount { +func newSCSIMount( + uvm *UtilityVM, + hostPath string, + uvmPath string, + attachmentType string, + evdType string, + refCount uint32, + controller int, + lun int32, + readOnly bool, + encrypted bool, +) *SCSIMount { return &SCSIMount{ vm: uvm, HostPath: hostPath, @@ -141,6 +156,7 @@ func newSCSIMount(uvm *UtilityVM, hostPath, uvmPath, attachmentType, evdType str refCount: refCount, Controller: controller, LUN: int32(lun), + encrypted: encrypted, readOnly: readOnly, attachmentType: attachmentType, extensibleVirtualDiskType: evdType, @@ -260,7 +276,7 @@ func (uvm *UtilityVM) RemoveSCSI(ctx context.Context, hostPath string) error { } // AddSCSI adds a SCSI disk to a utility VM at the next available location. This -// function should be called for a adding a scratch layer, a read-only layer as an +// function should be called for adding a scratch layer, a read-only layer as an // alternative to VPMEM, or for other VHD mounts. // // `hostPath` is required and must point to a vhd/vhdx path. @@ -269,16 +285,29 @@ func (uvm *UtilityVM) RemoveSCSI(ctx context.Context, hostPath string) error { // // `readOnly` set to `true` if the vhd/vhdx should be attached read only. // +// `encrypted` set to `true` if the vhd/vhdx should be attached in encrypted mode. +// The device will be formatted, so this option must be used only when creating +// scratch vhd/vhdx. +// // `guestOptions` is a slice that contains optional information to pass // to the guest service // // `vmAccess` indicates what access to grant the vm for the hostpath -func (uvm *UtilityVM) AddSCSI(ctx context.Context, hostPath string, uvmPath string, readOnly bool, guestOptions []string, vmAccess VMAccessType) (*SCSIMount, error) { +func (uvm *UtilityVM) AddSCSI( + ctx context.Context, + hostPath string, + uvmPath string, + readOnly bool, + encrypted bool, + guestOptions []string, + vmAccess VMAccessType, +) (*SCSIMount, error) { addReq := &addSCSIRequest{ hostPath: hostPath, uvmPath: uvmPath, attachmentType: "VirtualDisk", readOnly: readOnly, + encrypted: encrypted, guestOptions: guestOptions, vmAccess: VMAccessTypeIndividual, } @@ -350,7 +379,16 @@ func (uvm *UtilityVM) AddSCSIExtensibleVirtualDisk(ctx context.Context, hostPath // // Returns result from calling modify with the given scsi mount func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) (sm *SCSIMount, err error) { - sm, existed, err := uvm.allocateSCSIMount(ctx, addReq.readOnly, addReq.hostPath, addReq.uvmPath, addReq.attachmentType, addReq.evdType, addReq.vmAccess) + sm, existed, err := uvm.allocateSCSIMount( + ctx, + addReq.readOnly, + addReq.encrypted, + addReq.hostPath, + addReq.uvmPath, + addReq.attachmentType, + addReq.evdType, + addReq.vmAccess, + ) if err != nil { return nil, err } @@ -415,6 +453,7 @@ func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) Lun: uint8(sm.LUN), Controller: uint8(sm.Controller), ReadOnly: addReq.readOnly, + Encrypted: addReq.encrypted, Options: addReq.guestOptions, VerityInfo: verity, } @@ -432,7 +471,16 @@ func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) // device or allocates a new one if not already present. // Returns the resulting *SCSIMount, a bool indicating if the scsi device was already present, // and error if any. -func (uvm *UtilityVM) allocateSCSIMount(ctx context.Context, readOnly bool, hostPath, uvmPath, attachmentType, evdType string, vmAccess VMAccessType) (*SCSIMount, bool, error) { +func (uvm *UtilityVM) allocateSCSIMount( + ctx context.Context, + readOnly bool, + encrypted bool, + hostPath string, + uvmPath string, + attachmentType string, + evdType string, + vmAccess VMAccessType, +) (*SCSIMount, bool, error) { if attachmentType != "ExtensibleVirtualDisk" { // Ensure the utility VM has access err := grantAccess(ctx, uvm.id, hostPath, vmAccess) @@ -456,7 +504,18 @@ func (uvm *UtilityVM) allocateSCSIMount(ctx context.Context, readOnly bool, host return nil, false, err } - uvm.scsiLocations[controller][lun] = newSCSIMount(uvm, hostPath, uvmPath, attachmentType, evdType, 1, controller, int32(lun), readOnly) + uvm.scsiLocations[controller][lun] = newSCSIMount( + uvm, + hostPath, + uvmPath, + attachmentType, + evdType, + 1, + controller, + int32(lun), + readOnly, + encrypted, + ) log.G(ctx).WithFields(uvm.scsiLocations[controller][lun].logFormat()).Debug("allocated SCSI mount") @@ -477,6 +536,13 @@ func (uvm *UtilityVM) GetScsiUvmPath(ctx context.Context, hostPath string) (stri return sm.UVMPath, err } +// ScratchEncryptionEnabled is a getter for `uvm.encryptScratch`. +// +// Returns true if the scratch disks should be encrypted, false otherwise. +func (uvm *UtilityVM) ScratchEncryptionEnabled() bool { + return uvm.encryptScratch +} + // grantAccess helper function to grant access to a file for the vm or vm group func grantAccess(ctx context.Context, uvmID string, hostPath string, vmAccess VMAccessType) error { switch vmAccess { @@ -635,7 +701,18 @@ func (sm *SCSIMount) Clone(ctx context.Context, vm *UtilityVM, cd *cloneData) er Type_: sm.attachmentType, } - clonedScsiMount := newSCSIMount(vm, dstVhdPath, sm.UVMPath, sm.attachmentType, sm.extensibleVirtualDiskType, 1, sm.Controller, sm.LUN, sm.readOnly) + clonedScsiMount := newSCSIMount( + vm, + dstVhdPath, + sm.UVMPath, + sm.attachmentType, + sm.extensibleVirtualDiskType, + 1, + sm.Controller, + sm.LUN, + sm.readOnly, + sm.encrypted, + ) vm.scsiLocations[sm.Controller][sm.LUN] = clonedScsiMount diff --git a/internal/uvm/types.go b/internal/uvm/types.go index 1e568db98b..728c97ff68 100644 --- a/internal/uvm/types.go +++ b/internal/uvm/types.go @@ -83,6 +83,7 @@ type UtilityVM struct { // SCSI devices that are mapped into a Windows or Linux utility VM scsiLocations [4][64]*SCSIMount // Hyper-V supports 4 controllers, 64 slots per controller. Limited to 1 controller for now though. scsiControllerCount uint32 // Number of SCSI controllers in the utility VM + encryptScratch bool // Enable scratch encryption vpciDevices map[string]*VPCIDevice // map of device instance id to vpci device diff --git a/test/functional/lcow_test.go b/test/functional/lcow_test.go index b86392d7c3..42a63796a7 100644 --- a/test/functional/lcow_test.go +++ b/test/functional/lcow_test.go @@ -145,7 +145,7 @@ func TestLCOWSimplePodScenario(t *testing.T) { } var options []string - if _, err := lcowUVM.AddSCSI(context.Background(), uvmScratchFile, `/tmp/scratch`, false, options, uvm.VMAccessTypeIndividual); err != nil { + if _, err := lcowUVM.AddSCSI(context.Background(), uvmScratchFile, `/tmp/scratch`, false, false, options, uvm.VMAccessTypeIndividual); err != nil { t.Fatal(err) } diff --git a/test/functional/uvm_scratch_test.go b/test/functional/uvm_scratch_test.go index fe5041ad25..3ab78198e7 100644 --- a/test/functional/uvm_scratch_test.go +++ b/test/functional/uvm_scratch_test.go @@ -46,7 +46,7 @@ func TestScratchCreateLCOW(t *testing.T) { // Make sure it can be added (verifies it has access correctly) var options []string - scsiMount, err := targetUVM.AddSCSI(context.Background(), destTwo, "", false, options, uvm.VMAccessTypeIndividual) + scsiMount, err := targetUVM.AddSCSI(context.Background(), destTwo, "", false, false, options, uvm.VMAccessTypeIndividual) if err != nil { t.Fatal(err) } diff --git a/test/functional/uvm_scsi_test.go b/test/functional/uvm_scsi_test.go index 4a9962d422..60a27dd38a 100644 --- a/test/functional/uvm_scsi_test.go +++ b/test/functional/uvm_scsi_test.go @@ -52,7 +52,7 @@ func testAddSCSI(u *uvm.UtilityVM, disks []string, pathPrefix string, usePath bo uvmPath = fmt.Sprintf(`%s%d`, pathPrefix, i) } var options []string - scsiMount, err := u.AddSCSI(context.Background(), disks[i], uvmPath, false, options, uvm.VMAccessTypeIndividual) + scsiMount, err := u.AddSCSI(context.Background(), disks[i], uvmPath, false, false, options, uvm.VMAccessTypeIndividual) if err != nil { return err } @@ -277,7 +277,7 @@ func TestParallelScsiOps(t *testing.T) { } var options []string - _, err = u.AddSCSI(context.Background(), path, "", false, options, uvm.VMAccessTypeIndividual) + _, err = u.AddSCSI(context.Background(), path, "", false, false, options, uvm.VMAccessTypeIndividual) if err != nil { os.Remove(path) t.Errorf("failed to AddSCSI for worker: %d, iteration: %d with err: %v", scsiIndex, iteration, err) @@ -290,7 +290,7 @@ func TestParallelScsiOps(t *testing.T) { break } - _, err = u.AddSCSI(context.Background(), path, fmt.Sprintf("/run/gcs/c/0/scsi/%d", iteration), false, options, uvm.VMAccessTypeIndividual) + _, err = u.AddSCSI(context.Background(), path, fmt.Sprintf("/run/gcs/c/0/scsi/%d", iteration), false, false, options, uvm.VMAccessTypeIndividual) if err != nil { os.Remove(path) t.Errorf("failed to AddSCSI for worker: %d, iteration: %d with err: %v", scsiIndex, iteration, err) diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go b/test/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go index 5e1dd51caf..6d81dc11c8 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go @@ -37,6 +37,7 @@ type LCOWMappedVirtualDisk struct { Lun uint8 `json:"Lun,omitempty"` Controller uint8 `json:"Controller,omitempty"` ReadOnly bool `json:"ReadOnly,omitempty"` + Encrypted bool `json:"Encrypted,omitempty"` Options []string `json:"Options,omitempty"` VerityInfo *DeviceVerityInfo `json:"VerityInfo,omitempty"` } diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_lcow.go b/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_lcow.go index c01a1c18f6..a11f22ab83 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_lcow.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_lcow.go @@ -108,7 +108,15 @@ func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r * // if the scsi device is already attached then we take the uvm path that the function below returns // that is where it was previously mounted in UVM - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, hostPath, uvmPathForShare, readOnly, mount.Options, uvm.VMAccessTypeIndividual) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + hostPath, + uvmPathForShare, + readOnly, + false, + mount.Options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount) } @@ -188,7 +196,15 @@ func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r * // must use scsi here since DDA'ing a hyper-v pci device is not supported on VMs that have ANY virtual memory // gpuvhd must be granted VM Group access. options := []string{"ro"} - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, gpuSupportVhdPath, uvm.LCOWNvidiaMountPath, true, options, uvm.VMAccessTypeNoop) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + gpuSupportVhdPath, + uvm.LCOWNvidiaMountPath, + true, + false, + options, + uvm.VMAccessTypeNoop, + ) if err != nil { return errors.Wrapf(err, "failed to add scsi device %s in the UVM %s at %s", gpuSupportVhdPath, coi.HostingSystem.ID(), uvm.LCOWNvidiaMountPath) } diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_wcow.go b/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_wcow.go index ef7c8c1373..84240406c3 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_wcow.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/hcsoci/resources_wcow.go @@ -159,7 +159,15 @@ func setupMounts(ctx context.Context, coi *createOptionsInternal, r *resources.R r.Add(scsiMount) } else if mount.Type == "virtual-disk" { l.Debug("hcsshim::allocateWindowsResources Hot-adding SCSI virtual disk for OCI mount") - scsiMount, err := coi.HostingSystem.AddSCSI(ctx, mount.Source, uvmPath, readOnly, mount.Options, uvm.VMAccessTypeIndividual) + scsiMount, err := coi.HostingSystem.AddSCSI( + ctx, + mount.Source, + uvmPath, + readOnly, + false, + mount.Options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount) } diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/layers/layers.go b/test/vendor/github.com/Microsoft/hcsshim/internal/layers/layers.go index 146f9accf2..0cf06b92d7 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/layers/layers.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/layers/layers.go @@ -216,7 +216,15 @@ func MountContainerLayers(ctx context.Context, containerID string, layerFolders log.G(ctx).WithField("hostPath", hostPath).Debug("mounting scratch VHD") var options []string - scsiMount, err := vm.AddSCSI(ctx, hostPath, containerScratchPathInUVM, false, options, uvm.VMAccessTypeIndividual) + scsiMount, err := vm.AddSCSI( + ctx, + hostPath, + containerScratchPathInUVM, + false, + vm.ScratchEncryptionEnabled(), + options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return "", fmt.Errorf("failed to add SCSI scratch VHD: %s", err) } @@ -280,7 +288,7 @@ func addLCOWLayer(ctx context.Context, vm *uvm.UtilityVM, layerPath string) (uvm options := []string{"ro"} uvmPath = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, vm.UVMMountCounter()) - sm, err := vm.AddSCSI(ctx, layerPath, uvmPath, true, options, uvm.VMAccessTypeNoop) + sm, err := vm.AddSCSI(ctx, layerPath, uvmPath, true, false, options, uvm.VMAccessTypeNoop) if err != nil { return "", fmt.Errorf("failed to add SCSI layer: %s", err) } diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/lcow/scratch.go b/test/vendor/github.com/Microsoft/hcsshim/internal/lcow/scratch.go index 12884b4745..ae385a1c1b 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/lcow/scratch.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/lcow/scratch.go @@ -67,7 +67,15 @@ func CreateScratch(ctx context.Context, lcowUVM *uvm.UtilityVM, destFile string, } var options []string - scsi, err := lcowUVM.AddSCSI(ctx, destFile, "", false, options, uvm.VMAccessTypeIndividual) // No destination as not formatted + scsi, err := lcowUVM.AddSCSI( + ctx, + destFile, + "", // No destination as not formatted + false, + lcowUVM.ScratchEncryptionEnabled(), + options, + uvm.VMAccessTypeIndividual, + ) if err != nil { return err } diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/oci/annotations.go b/test/vendor/github.com/Microsoft/hcsshim/internal/oci/annotations.go index d56611162a..bff3740512 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/oci/annotations.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/oci/annotations.go @@ -214,6 +214,10 @@ const ( // when setting up ncproxy and computeagent AnnotationNcproxyContainerID = "io.microsoft.network.ncproxy.containerid" + // AnnotationEncryptedScratchDisk indicates whether or not the container scratch disks + // should be encrypted or not + AnnotationEncryptedScratchDisk = "io.microsoft.virtualmachine.storage.scratch.encrypted" + // AnnotationSecurityPolicy is used to specify a security policy for opengcs to enforce AnnotationSecurityPolicy = "io.microsoft.virtualmachine.lcow.securitypolicy" ) diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/oci/uvm.go b/test/vendor/github.com/Microsoft/hcsshim/internal/oci/uvm.go index 380795094c..264f6a1a6d 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/oci/uvm.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/oci/uvm.go @@ -329,6 +329,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) ( lopts.BootFilesPath = parseAnnotationsString(s.Annotations, AnnotationBootFilesRootPath, lopts.BootFilesPath) lopts.CPUGroupID = parseAnnotationsString(s.Annotations, AnnotationCPUGroupID, lopts.CPUGroupID) lopts.NetworkConfigProxy = parseAnnotationsString(s.Annotations, AnnotationNetworkConfigProxy, lopts.NetworkConfigProxy) + lopts.EnableScratchEncryption = parseAnnotationsBool(ctx, s.Annotations, AnnotationEncryptedScratchDisk, lopts.EnableScratchEncryption) lopts.SecurityPolicy = parseAnnotationsString(s.Annotations, AnnotationSecurityPolicy, lopts.SecurityPolicy) lopts.KernelBootOptions = parseAnnotationsString(s.Annotations, AnnotationKernelBootOptions, lopts.KernelBootOptions) diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_lcow.go b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_lcow.go index 380cdccc84..5fb631cb6e 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_lcow.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_lcow.go @@ -56,26 +56,27 @@ const ( type OptionsLCOW struct { *Options - BootFilesPath string // Folder in which kernel and root file system reside. Defaults to \Program Files\Linux Containers - KernelFile string // Filename under `BootFilesPath` for the kernel. Defaults to `kernel` - KernelDirect bool // Skip UEFI and boot directly to `kernel` - RootFSFile string // Filename under `BootFilesPath` for the UVMs root file system. Defaults to `InitrdFile` - KernelBootOptions string // Additional boot options for the kernel - EnableGraphicsConsole bool // If true, enable a graphics console for the utility VM - ConsolePipe string // The named pipe path to use for the serial console. eg \\.\pipe\vmpipe - SCSIControllerCount uint32 // The number of SCSI controllers. Defaults to 1. Currently we only support 0 or 1. - UseGuestConnection bool // Whether the HCS should connect to the UVM's GCS. Defaults to true - ExecCommandLine string // The command line to exec from init. Defaults to GCS - ForwardStdout bool // Whether stdout will be forwarded from the executed program. Defaults to false - ForwardStderr bool // Whether stderr will be forwarded from the executed program. Defaults to true - OutputHandler OutputHandler `json:"-"` // Controls how output received over HVSocket from the UVM is handled. Defaults to parsing output as logrus messages - VPMemDeviceCount uint32 // Number of VPMem devices. Defaults to `DefaultVPMEMCount`. Limit at 128. If booting UVM from VHD, device 0 is taken. - VPMemSizeBytes uint64 // Size of the VPMem devices. Defaults to `DefaultVPMemSizeBytes`. - VPMemNoMultiMapping bool // Disables LCOW layer multi mapping - PreferredRootFSType PreferredRootFSType // If `KernelFile` is `InitrdFile` use `PreferredRootFSTypeInitRd`. If `KernelFile` is `VhdFile` use `PreferredRootFSTypeVHD` - EnableColdDiscardHint bool // Whether the HCS should use cold discard hints. Defaults to false - VPCIEnabled bool // Whether the kernel should enable pci - SecurityPolicy string // Optional security policy + BootFilesPath string // Folder in which kernel and root file system reside. Defaults to \Program Files\Linux Containers + KernelFile string // Filename under `BootFilesPath` for the kernel. Defaults to `kernel` + KernelDirect bool // Skip UEFI and boot directly to `kernel` + RootFSFile string // Filename under `BootFilesPath` for the UVMs root file system. Defaults to `InitrdFile` + KernelBootOptions string // Additional boot options for the kernel + EnableGraphicsConsole bool // If true, enable a graphics console for the utility VM + ConsolePipe string // The named pipe path to use for the serial console. eg \\.\pipe\vmpipe + SCSIControllerCount uint32 // The number of SCSI controllers. Defaults to 1. Currently we only support 0 or 1. + UseGuestConnection bool // Whether the HCS should connect to the UVM's GCS. Defaults to true + ExecCommandLine string // The command line to exec from init. Defaults to GCS + ForwardStdout bool // Whether stdout will be forwarded from the executed program. Defaults to false + ForwardStderr bool // Whether stderr will be forwarded from the executed program. Defaults to true + OutputHandler OutputHandler `json:"-"` // Controls how output received over HVSocket from the UVM is handled. Defaults to parsing output as logrus messages + VPMemDeviceCount uint32 // Number of VPMem devices. Defaults to `DefaultVPMEMCount`. Limit at 128. If booting UVM from VHD, device 0 is taken. + VPMemSizeBytes uint64 // Size of the VPMem devices. Defaults to `DefaultVPMemSizeBytes`. + VPMemNoMultiMapping bool // Disables LCOW layer multi mapping + PreferredRootFSType PreferredRootFSType // If `KernelFile` is `InitrdFile` use `PreferredRootFSTypeInitRd`. If `KernelFile` is `VhdFile` use `PreferredRootFSTypeVHD` + EnableColdDiscardHint bool // Whether the HCS should use cold discard hints. Defaults to false + VPCIEnabled bool // Whether the kernel should enable pci + EnableScratchEncryption bool // Whether the scratch should be encrypted + SecurityPolicy string // Optional security policy } // defaultLCOWOSBootFilesPath returns the default path used to locate the LCOW @@ -101,27 +102,28 @@ func NewDefaultOptionsLCOW(id, owner string) *OptionsLCOW { // Use KernelDirect boot by default on all builds that support it. kernelDirectSupported := osversion.Build() >= 18286 opts := &OptionsLCOW{ - Options: newDefaultOptions(id, owner), - BootFilesPath: defaultLCOWOSBootFilesPath(), - KernelFile: KernelFile, - KernelDirect: kernelDirectSupported, - RootFSFile: InitrdFile, - KernelBootOptions: "", - EnableGraphicsConsole: false, - ConsolePipe: "", - SCSIControllerCount: 1, - UseGuestConnection: true, - ExecCommandLine: fmt.Sprintf("/bin/gcs -v4 -log-format json -loglevel %s", logrus.StandardLogger().Level.String()), - ForwardStdout: false, - ForwardStderr: true, - OutputHandler: parseLogrus(id), - VPMemDeviceCount: DefaultVPMEMCount, - VPMemSizeBytes: DefaultVPMemSizeBytes, - VPMemNoMultiMapping: osversion.Get().Build < osversion.V19H1, - PreferredRootFSType: PreferredRootFSTypeInitRd, - EnableColdDiscardHint: false, - VPCIEnabled: false, - SecurityPolicy: "", + Options: newDefaultOptions(id, owner), + BootFilesPath: defaultLCOWOSBootFilesPath(), + KernelFile: KernelFile, + KernelDirect: kernelDirectSupported, + RootFSFile: InitrdFile, + KernelBootOptions: "", + EnableGraphicsConsole: false, + ConsolePipe: "", + SCSIControllerCount: 1, + UseGuestConnection: true, + ExecCommandLine: fmt.Sprintf("/bin/gcs -v4 -log-format json -loglevel %s", logrus.StandardLogger().Level.String()), + ForwardStdout: false, + ForwardStderr: true, + OutputHandler: parseLogrus(id), + VPMemDeviceCount: DefaultVPMEMCount, + VPMemSizeBytes: DefaultVPMemSizeBytes, + VPMemNoMultiMapping: osversion.Get().Build < osversion.V19H1, + PreferredRootFSType: PreferredRootFSTypeInitRd, + EnableColdDiscardHint: false, + VPCIEnabled: false, + EnableScratchEncryption: false, + SecurityPolicy: "", } if _, err := os.Stat(filepath.Join(opts.BootFilesPath, VhdFile)); err == nil { @@ -176,6 +178,7 @@ func CreateLCOW(ctx context.Context, opts *OptionsLCOW) (_ *UtilityVM, err error devicesPhysicallyBacked: opts.FullyPhysicallyBacked, createOpts: opts, vpmemMultiMapping: !opts.VPMemNoMultiMapping, + encryptScratch: opts.EnableScratchEncryption, } defer func() { diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_wcow.go b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_wcow.go index b00b0feee3..1bd15d203e 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_wcow.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/create_wcow.go @@ -296,6 +296,7 @@ func CreateWCOW(ctx context.Context, opts *OptionsWCOW) (_ *UtilityVM, err error 1, 0, 0, + false, false) } else { doc.VirtualMachine.RestoreState = &hcsschema.RestoreState{} diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/scsi.go b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/scsi.go index 5d891a2e2b..49c4b210a2 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/scsi.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/scsi.go @@ -77,6 +77,8 @@ type SCSIMount struct { // read-only layers. As RO layers are shared, we perform ref-counting. isLayer bool refCount uint32 + // specifies if this is an encrypted VHD + encrypted bool // specifies if this is a readonly layer readOnly bool // "VirtualDisk" or "PassThru" or "ExtensibleVirtualDisk" disk attachment type. @@ -102,6 +104,8 @@ type addSCSIRequest struct { // attachments, `PassThru` for physical disk and `ExtensibleVirtualDisk` for // Extensible virtual disks. attachmentType string + // indicates if the VHD is encrypted + encrypted bool // indicates if the attachment should be added read only. readOnly bool // guestOptions is a slice that contains optional information to pass to the guest @@ -133,7 +137,18 @@ func (sm *SCSIMount) logFormat() logrus.Fields { } } -func newSCSIMount(uvm *UtilityVM, hostPath, uvmPath, attachmentType, evdType string, refCount uint32, controller int, lun int32, readOnly bool) *SCSIMount { +func newSCSIMount( + uvm *UtilityVM, + hostPath string, + uvmPath string, + attachmentType string, + evdType string, + refCount uint32, + controller int, + lun int32, + readOnly bool, + encrypted bool, +) *SCSIMount { return &SCSIMount{ vm: uvm, HostPath: hostPath, @@ -141,6 +156,7 @@ func newSCSIMount(uvm *UtilityVM, hostPath, uvmPath, attachmentType, evdType str refCount: refCount, Controller: controller, LUN: int32(lun), + encrypted: encrypted, readOnly: readOnly, attachmentType: attachmentType, extensibleVirtualDiskType: evdType, @@ -260,7 +276,7 @@ func (uvm *UtilityVM) RemoveSCSI(ctx context.Context, hostPath string) error { } // AddSCSI adds a SCSI disk to a utility VM at the next available location. This -// function should be called for a adding a scratch layer, a read-only layer as an +// function should be called for adding a scratch layer, a read-only layer as an // alternative to VPMEM, or for other VHD mounts. // // `hostPath` is required and must point to a vhd/vhdx path. @@ -269,16 +285,29 @@ func (uvm *UtilityVM) RemoveSCSI(ctx context.Context, hostPath string) error { // // `readOnly` set to `true` if the vhd/vhdx should be attached read only. // +// `encrypted` set to `true` if the vhd/vhdx should be attached in encrypted mode. +// The device will be formatted, so this option must be used only when creating +// scratch vhd/vhdx. +// // `guestOptions` is a slice that contains optional information to pass // to the guest service // // `vmAccess` indicates what access to grant the vm for the hostpath -func (uvm *UtilityVM) AddSCSI(ctx context.Context, hostPath string, uvmPath string, readOnly bool, guestOptions []string, vmAccess VMAccessType) (*SCSIMount, error) { +func (uvm *UtilityVM) AddSCSI( + ctx context.Context, + hostPath string, + uvmPath string, + readOnly bool, + encrypted bool, + guestOptions []string, + vmAccess VMAccessType, +) (*SCSIMount, error) { addReq := &addSCSIRequest{ hostPath: hostPath, uvmPath: uvmPath, attachmentType: "VirtualDisk", readOnly: readOnly, + encrypted: encrypted, guestOptions: guestOptions, vmAccess: VMAccessTypeIndividual, } @@ -350,7 +379,16 @@ func (uvm *UtilityVM) AddSCSIExtensibleVirtualDisk(ctx context.Context, hostPath // // Returns result from calling modify with the given scsi mount func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) (sm *SCSIMount, err error) { - sm, existed, err := uvm.allocateSCSIMount(ctx, addReq.readOnly, addReq.hostPath, addReq.uvmPath, addReq.attachmentType, addReq.evdType, addReq.vmAccess) + sm, existed, err := uvm.allocateSCSIMount( + ctx, + addReq.readOnly, + addReq.encrypted, + addReq.hostPath, + addReq.uvmPath, + addReq.attachmentType, + addReq.evdType, + addReq.vmAccess, + ) if err != nil { return nil, err } @@ -415,6 +453,7 @@ func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) Lun: uint8(sm.LUN), Controller: uint8(sm.Controller), ReadOnly: addReq.readOnly, + Encrypted: addReq.encrypted, Options: addReq.guestOptions, VerityInfo: verity, } @@ -432,7 +471,16 @@ func (uvm *UtilityVM) addSCSIActual(ctx context.Context, addReq *addSCSIRequest) // device or allocates a new one if not already present. // Returns the resulting *SCSIMount, a bool indicating if the scsi device was already present, // and error if any. -func (uvm *UtilityVM) allocateSCSIMount(ctx context.Context, readOnly bool, hostPath, uvmPath, attachmentType, evdType string, vmAccess VMAccessType) (*SCSIMount, bool, error) { +func (uvm *UtilityVM) allocateSCSIMount( + ctx context.Context, + readOnly bool, + encrypted bool, + hostPath string, + uvmPath string, + attachmentType string, + evdType string, + vmAccess VMAccessType, +) (*SCSIMount, bool, error) { if attachmentType != "ExtensibleVirtualDisk" { // Ensure the utility VM has access err := grantAccess(ctx, uvm.id, hostPath, vmAccess) @@ -456,7 +504,18 @@ func (uvm *UtilityVM) allocateSCSIMount(ctx context.Context, readOnly bool, host return nil, false, err } - uvm.scsiLocations[controller][lun] = newSCSIMount(uvm, hostPath, uvmPath, attachmentType, evdType, 1, controller, int32(lun), readOnly) + uvm.scsiLocations[controller][lun] = newSCSIMount( + uvm, + hostPath, + uvmPath, + attachmentType, + evdType, + 1, + controller, + int32(lun), + readOnly, + encrypted, + ) log.G(ctx).WithFields(uvm.scsiLocations[controller][lun].logFormat()).Debug("allocated SCSI mount") @@ -477,6 +536,13 @@ func (uvm *UtilityVM) GetScsiUvmPath(ctx context.Context, hostPath string) (stri return sm.UVMPath, err } +// ScratchEncryptionEnabled is a getter for `uvm.encryptScratch`. +// +// Returns true if the scratch disks should be encrypted, false otherwise. +func (uvm *UtilityVM) ScratchEncryptionEnabled() bool { + return uvm.encryptScratch +} + // grantAccess helper function to grant access to a file for the vm or vm group func grantAccess(ctx context.Context, uvmID string, hostPath string, vmAccess VMAccessType) error { switch vmAccess { @@ -635,7 +701,18 @@ func (sm *SCSIMount) Clone(ctx context.Context, vm *UtilityVM, cd *cloneData) er Type_: sm.attachmentType, } - clonedScsiMount := newSCSIMount(vm, dstVhdPath, sm.UVMPath, sm.attachmentType, sm.extensibleVirtualDiskType, 1, sm.Controller, sm.LUN, sm.readOnly) + clonedScsiMount := newSCSIMount( + vm, + dstVhdPath, + sm.UVMPath, + sm.attachmentType, + sm.extensibleVirtualDiskType, + 1, + sm.Controller, + sm.LUN, + sm.readOnly, + sm.encrypted, + ) vm.scsiLocations[sm.Controller][sm.LUN] = clonedScsiMount diff --git a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/types.go b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/types.go index 1e568db98b..728c97ff68 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/types.go +++ b/test/vendor/github.com/Microsoft/hcsshim/internal/uvm/types.go @@ -83,6 +83,7 @@ type UtilityVM struct { // SCSI devices that are mapped into a Windows or Linux utility VM scsiLocations [4][64]*SCSIMount // Hyper-V supports 4 controllers, 64 slots per controller. Limited to 1 controller for now though. scsiControllerCount uint32 // Number of SCSI controllers in the utility VM + encryptScratch bool // Enable scratch encryption vpciDevices map[string]*VPCIDevice // map of device instance id to vpci device