...

Source file src/github.com/Microsoft/hcsshim/internal/uvm/security_policy.go

Documentation: github.com/Microsoft/hcsshim/internal/uvm

     1  //go:build windows
     2  
     3  package uvm
     4  
     5  import (
     6  	"context"
     7  	"encoding/base64"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  
    12  	hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
    13  	"github.com/Microsoft/hcsshim/internal/log"
    14  	"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
    15  	"github.com/Microsoft/hcsshim/internal/protocol/guestresource"
    16  	"github.com/Microsoft/hcsshim/pkg/ctrdtaskapi"
    17  )
    18  
    19  type ConfidentialUVMOpt func(ctx context.Context, r *guestresource.LCOWConfidentialOptions) error
    20  
    21  // WithSecurityPolicy sets the desired security policy for the resource.
    22  func WithSecurityPolicy(policy string) ConfidentialUVMOpt {
    23  	return func(ctx context.Context, r *guestresource.LCOWConfidentialOptions) error {
    24  		r.EncodedSecurityPolicy = policy
    25  		return nil
    26  	}
    27  }
    28  
    29  // WithSecurityPolicyEnforcer sets the desired enforcer type for the resource.
    30  func WithSecurityPolicyEnforcer(enforcer string) ConfidentialUVMOpt {
    31  	return func(ctx context.Context, r *guestresource.LCOWConfidentialOptions) error {
    32  		r.EnforcerType = enforcer
    33  		return nil
    34  	}
    35  }
    36  
    37  func base64EncodeFileContents(filePath string) (string, error) {
    38  	if filePath == "" {
    39  		return "", nil
    40  	}
    41  	content, err := os.ReadFile(filePath)
    42  	if err != nil {
    43  		return "", err
    44  	}
    45  	return base64.StdEncoding.EncodeToString(content), nil
    46  }
    47  
    48  // WithUVMReferenceInfo reads UVM reference info file and base64 encodes the
    49  // content before setting it for the resource. This is no-op if the
    50  // `referenceName` is empty or the file doesn't exist.
    51  func WithUVMReferenceInfo(referenceRoot string, referenceName string) ConfidentialUVMOpt {
    52  	return func(ctx context.Context, r *guestresource.LCOWConfidentialOptions) error {
    53  		if referenceName == "" {
    54  			return nil
    55  		}
    56  		fullFilePath := filepath.Join(referenceRoot, referenceName)
    57  		encoded, err := base64EncodeFileContents(fullFilePath)
    58  		if err != nil {
    59  			if os.IsNotExist(err) {
    60  				log.G(ctx).WithField("filePath", fullFilePath).Debug("UVM reference info file not found")
    61  				return nil
    62  			}
    63  			return fmt.Errorf("failed to read UVM reference info file: %w", err)
    64  		}
    65  		r.EncodedUVMReference = encoded
    66  		return nil
    67  	}
    68  }
    69  
    70  // SetConfidentialUVMOptions sends information required to run the UVM on
    71  // SNP hardware, e.g., security policy and enforcer type, signed UVM reference
    72  // information, etc.
    73  //
    74  // This has to happen before we start mounting things or generally changing
    75  // the state of the UVM after is has been measured at startup
    76  func (uvm *UtilityVM) SetConfidentialUVMOptions(ctx context.Context, opts ...ConfidentialUVMOpt) error {
    77  	if uvm.operatingSystem != "linux" {
    78  		return errNotSupported
    79  	}
    80  
    81  	uvm.m.Lock()
    82  	defer uvm.m.Unlock()
    83  
    84  	confOpts := &guestresource.LCOWConfidentialOptions{}
    85  	for _, o := range opts {
    86  		if err := o(ctx, confOpts); err != nil {
    87  			return err
    88  		}
    89  	}
    90  	modification := &hcsschema.ModifySettingRequest{
    91  		RequestType: guestrequest.RequestTypeAdd,
    92  		GuestRequest: guestrequest.ModificationRequest{
    93  			ResourceType: guestresource.ResourceTypeSecurityPolicy,
    94  			RequestType:  guestrequest.RequestTypeAdd,
    95  			Settings:     *confOpts,
    96  		},
    97  	}
    98  
    99  	if err := uvm.modify(ctx, modification); err != nil {
   100  		return fmt.Errorf("uvm::Policy: failed to modify utility VM configuration: %s", err)
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  // InjectPolicyFragment sends policy fragment to GCS.
   107  func (uvm *UtilityVM) InjectPolicyFragment(ctx context.Context, fragment *ctrdtaskapi.PolicyFragment) error {
   108  	if uvm.operatingSystem != "linux" {
   109  		return errNotSupported
   110  	}
   111  	mod := &hcsschema.ModifySettingRequest{
   112  		RequestType: guestrequest.RequestTypeUpdate,
   113  		GuestRequest: guestrequest.ModificationRequest{
   114  			ResourceType: guestresource.ResourceTypePolicyFragment,
   115  			RequestType:  guestrequest.RequestTypeAdd,
   116  			Settings: guestresource.LCOWSecurityPolicyFragment{
   117  				Fragment: fragment.Fragment,
   118  			},
   119  		},
   120  	}
   121  	return uvm.modify(ctx, mod)
   122  }
   123  

View as plain text