Skip to content

Commit 8a094ae

Browse files
authored
tests: add rego e2e tests for dump_stacks and get_properties (#1793)
Signed-off-by: Maksim An <[email protected]>
1 parent 4f8d26f commit 8a094ae

1 file changed

Lines changed: 164 additions & 24 deletions

File tree

test/cri-containerd/policy_test.go

Lines changed: 164 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
110128
func 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

Comments
 (0)