@@ -15,6 +15,7 @@ import (
1515 "testing"
1616 "time"
1717
18+ "github.com/Microsoft/hcsshim/internal/shimdiag"
1819 runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
1920
2021 "github.com/Microsoft/hcsshim/pkg/annotations"
@@ -74,39 +75,56 @@ func policyFromOpts(t *testing.T, policyType string, opts ...securitypolicy.Poli
7475 return base64 .StdEncoding .EncodeToString ([]byte (policyString ))
7576}
7677
77- func securityPolicyFromImageWithOpts (t * testing.T , imageName string , policyType string , allowEnvironmentVariableDropping bool , allowCapabilityDropping bool , opts ... securitypolicy.ContainerConfigOpt ) string {
78+ func alpineSecurityPolicy (t * testing.T , policyType string , allowEnvironmentVariableDropping bool , allowCapabilityDropping bool , opts ... securitypolicy.ContainerConfigOpt ) string {
7879 t .Helper ()
79- alpineContainer := securitypolicy.ContainerConfig {
80- ImageName : imageName ,
81- Command : validPolicyAlpineCommand ,
82- AllowPrivilegeEscalation : true ,
83- }
80+ containerConfigOpts := append (
81+ []securitypolicy.ContainerConfigOpt {
82+ securitypolicy .WithCommand (validPolicyAlpineCommand ),
83+ securitypolicy .WithAllowPrivilegeEscalation (true ),
84+ },
85+ opts ... ,
86+ )
87+ return policyFromImageWithOpts (
88+ t ,
89+ imageLcowAlpine ,
90+ policyType ,
91+ []securitypolicy.PolicyConfigOpt {
92+ securitypolicy .WithAllowEnvVarDropping (allowEnvironmentVariableDropping ),
93+ securitypolicy .WithAllowCapabilityDropping (allowCapabilityDropping ),
94+ },
95+ containerConfigOpts ,
96+ )
97+ }
8498
85- for _ , o := range opts {
86- if err := o (& alpineContainer ); err != nil {
87- t .Fatalf ("failed to apply config opt: %s" , err )
99+ func policyFromImageWithOpts (
100+ t * testing.T ,
101+ imageName string ,
102+ policyType string ,
103+ policyOpts []securitypolicy.PolicyConfigOpt ,
104+ containerOpts []securitypolicy.ContainerConfigOpt ,
105+ ) string {
106+ t .Helper ()
107+ containerConfig := securitypolicy.ContainerConfig {
108+ ImageName : imageName ,
109+ }
110+ for _ , o := range containerOpts {
111+ if err := o (& containerConfig ); err != nil {
112+ t .Fatalf ("failed to apply container config opt: %s" , err )
88113 }
89114 }
90-
115+ finalPolicyOpts := append (
116+ []securitypolicy.PolicyConfigOpt {
117+ securitypolicy .WithContainers ([]securitypolicy.ContainerConfig {containerConfig }),
118+ },
119+ policyOpts ... ,
120+ )
91121 return policyFromOpts (
92122 t ,
93123 policyType ,
94- securitypolicy .WithContainers ([]securitypolicy.ContainerConfig {alpineContainer }),
95- securitypolicy .WithExternalProcesses (defaultExternalProcesses ),
96- securitypolicy .WithAllowUnencryptedScratch (true ),
97- securitypolicy .WithAllowEnvVarDropping (allowEnvironmentVariableDropping ),
98- securitypolicy .WithAllowCapabilityDropping (allowCapabilityDropping ),
99- securitypolicy .WithAllowRuntimeLogging (true ),
100- securitypolicy .WithAllowPropertiesAccess (true ),
101- securitypolicy .WithAllowDumpStacks (true ),
124+ finalPolicyOpts ... ,
102125 )
103126}
104127
105- func alpineSecurityPolicy (t * testing.T , policyType string , allowEnvironmentVariableDropping bool , allowCapabilityDropping bool , opts ... securitypolicy.ContainerConfigOpt ) string {
106- t .Helper ()
107- return securityPolicyFromImageWithOpts (t , imageLcowAlpine , policyType , allowEnvironmentVariableDropping , allowCapabilityDropping , opts ... )
108- }
109-
110128func sandboxRequestWithPolicy (t * testing.T , policy string ) * runtime.RunPodSandboxRequest {
111129 t .Helper ()
112130 return getRunPodSandboxRequest (
@@ -117,6 +135,7 @@ func sandboxRequestWithPolicy(t *testing.T, policy string) *runtime.RunPodSandbo
117135 annotations .NoSecurityHardware : strconv .FormatBool (! * flagSevSnp ),
118136 annotations .SecurityPolicy : policy ,
119137 annotations .VPMemNoMultiMapping : "true" ,
138+ annotations .VPMemCount : "0" ,
120139 // This allows for better experience for policy only tests.
121140 annotations .EncryptedScratchDisk : strconv .FormatBool (* flagSevSnp ),
122141 },
@@ -1533,7 +1552,19 @@ func Test_RunContainer_WithPolicy_And_RunAs(t *testing.T) {
15331552 defer cancel ()
15341553
15351554 cmd := []string {"sh" , "-c" , "echo 'Hello'" }
1536- policy := securityPolicyFromImageWithOpts (t , imageLcowCustomUser , "rego" , false , false , securitypolicy .WithCommand (cmd ), securitypolicy .WithUser (userConfig (1000 , 1000 )))
1555+ policy := policyFromImageWithOpts (
1556+ t ,
1557+ imageLcowCustomUser ,
1558+ "rego" ,
1559+ []securitypolicy.PolicyConfigOpt {
1560+ securitypolicy .WithAllowEnvVarDropping (false ),
1561+ securitypolicy .WithAllowCapabilityDropping (false ),
1562+ },
1563+ []securitypolicy.ContainerConfigOpt {
1564+ securitypolicy .WithCommand (cmd ),
1565+ securitypolicy .WithUser (userConfig (1000 , 1000 )),
1566+ },
1567+ )
15371568
15381569 for _ , config := range []struct {
15391570 name string
@@ -1970,3 +2001,112 @@ func Test_Plan9Mount_WithPolicy(t *testing.T) {
19702001 })
19712002 }
19722003}
2004+
2005+ func Test_DumpStacks_WithPolicy (t * testing.T ) {
2006+ requireFeatures (t , featureLCOWIntegrity )
2007+ pullRequiredLCOWImages (t , []string {imageLcowK8sPause })
2008+
2009+ client := newTestRuntimeClient (t )
2010+ ctx , cancel := context .WithCancel (context .Background ())
2011+ defer cancel ()
2012+
2013+ for _ , stacksAllowed := range []bool {true , false } {
2014+ t .Run (fmt .Sprintf ("Allowed_%t" , stacksAllowed ), func (t * testing.T ) {
2015+ policy := policyFromOpts (
2016+ t ,
2017+ "rego" ,
2018+ securitypolicy .WithAllowUnencryptedScratch (true ),
2019+ securitypolicy .WithAllowDumpStacks (stacksAllowed ),
2020+ )
2021+ sandboxRequest := sandboxRequestWithPolicy (t , policy )
2022+ sandboxRequest .Config .Annotations [annotations .EncryptedScratchDisk ] = "false"
2023+
2024+ podID := runPodSandbox (t , client , ctx , sandboxRequest )
2025+ defer removePodSandbox (t , client , ctx , podID )
2026+ defer stopPodSandbox (t , client , ctx , podID )
2027+
2028+ shimName := fmt .Sprintf ("k8s.io-%s" , podID )
2029+ shim , err := shimdiag .GetShim (shimName )
2030+ if err != nil {
2031+ t .Fatal (err )
2032+ }
2033+ shimClient := shimdiag .NewShimDiagClient (shim )
2034+
2035+ // note that this will always return at least the host stacks, but
2036+ // we need to explicitly check for the guest stacks to make sure
2037+ // that the enforcement works.
2038+ stacks , _ := shimClient .DiagStacks (ctx , & shimdiag.StacksRequest {})
2039+ if stacksAllowed {
2040+ if len (stacks .GuestStacks ) == 0 {
2041+ t .Fatal ("GCS stacks must be available" )
2042+ }
2043+ } else {
2044+ if len (stacks .GuestStacks ) > 0 {
2045+ t .Fatal ("GCS stacks must be empty" )
2046+ }
2047+ }
2048+ })
2049+ }
2050+ }
2051+
2052+ func Test_GetProperties_WithPolicy (t * testing.T ) {
2053+ requireFeatures (t , featureLCOWIntegrity )
2054+ pullRequiredLCOWImages (t , []string {imageLcowK8sPause , imageLcowAlpine })
2055+
2056+ client := newTestRuntimeClient (t )
2057+ ctx , cancel := context .WithCancel (context .Background ())
2058+ defer cancel ()
2059+
2060+ for _ , allowGetProperties := range []bool {true , false } {
2061+ t .Run (fmt .Sprintf ("Allowed_%t" , allowGetProperties ), func (t * testing.T ) {
2062+ policy := policyFromImageWithOpts (
2063+ t ,
2064+ imageLcowAlpine ,
2065+ "rego" ,
2066+ []securitypolicy.PolicyConfigOpt {
2067+ securitypolicy .WithAllowUnencryptedScratch (true ),
2068+ securitypolicy .WithAllowPropertiesAccess (allowGetProperties ),
2069+ },
2070+ []securitypolicy.ContainerConfigOpt {
2071+ securitypolicy .WithCommand (validPolicyAlpineCommand ),
2072+ securitypolicy .WithAllowPrivilegeEscalation (true ),
2073+ },
2074+ )
2075+ sandboxRequest := sandboxRequestWithPolicy (t , policy )
2076+ sandboxRequest .Config .Annotations [annotations .EncryptedScratchDisk ] = "false"
2077+
2078+ podID := runPodSandbox (t , client , ctx , sandboxRequest )
2079+ defer removePodSandbox (t , client , ctx , podID )
2080+ defer stopPodSandbox (t , client , ctx , podID )
2081+
2082+ containerRequest := getCreateContainerRequest (
2083+ podID ,
2084+ "alpine-get-properties" ,
2085+ imageLcowAlpine ,
2086+ validPolicyAlpineCommand ,
2087+ sandboxRequest .Config ,
2088+ )
2089+ containerID := createContainer (t , client , ctx , containerRequest )
2090+ defer removeContainer (t , client , ctx , containerID )
2091+ startContainer (t , client , ctx , containerID )
2092+ defer stopContainer (t , client , ctx , containerID )
2093+
2094+ _ , err := client .ContainerStats (ctx , & runtime.ContainerStatsRequest {ContainerId : containerID })
2095+ if err != nil {
2096+ if allowGetProperties {
2097+ t .Fatalf ("container stats should be allowed: %s" , err )
2098+ }
2099+ // unfortunately the errors returned during stats collection
2100+ // are not bubbled up, so we can only rely on the fact that
2101+ // the metrics response is invalid.
2102+ if ! strings .Contains (err .Error (), " unexpected metrics response: []" ) {
2103+ t .Fatalf ("expected different error: %s" , err )
2104+ }
2105+ } else {
2106+ if ! allowGetProperties {
2107+ t .Fatal ("container stats should not be allowed" )
2108+ }
2109+ }
2110+ })
2111+ }
2112+ }
0 commit comments