-
Notifications
You must be signed in to change notification settings - Fork 456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Additional Seccomp tests #137
Conversation
8a05047
to
32c8e24
Compare
@feiskyer Wish I'd known someone else was also drafting seccomp tests :-) |
@Random-Liu @feiskyer all good, I don't see any overlap in our test cases. I'll normalize and combine them on Monday. For example, he's using chmod and grep which should work with docker/default and they do not require caps to be set before generating the default seccomp profile (which from my investigation is different with and without certain caps and on different platforms). I'm using hostname which requires caps to make docker/default allow sethostname, so I'm testing with and without caps on to cover both fail and pass cases. I'm also testing the privileged case to make sure you can't block a command when privileged, and i've got a test for runtime/default as that may also be used instead of docker/default. And I just added a test to make sure the profile name is in the format "localhost/*" |
2c9f66d
to
edebeb8
Compare
@mikebrow Sorry for didn't let you know this. But cool with more complete test cases. |
@mikebrow needs a rebase now |
edebeb8
to
8da211a
Compare
Rebased. @feiskyer I see there was a change to the CRI api documentation kubernetes/kubernetes@c242432#diff-df996ad3ce05a000c2009d6e8cfba507L486 Talked to @Random-Liu about this. Will just remove the runtime/default tests for now. |
8da211a
to
3c2a89b
Compare
@Random-Liu @feiskyer rebased. Tests passing ready for review. |
pkg/validate/security_context.go
Outdated
@@ -402,6 +424,41 @@ var _ = framework.KubeDescribe("Security Context", func() { | |||
|
|||
checkNetworkManagement(rc, containerID, false) | |||
}) | |||
}) | |||
|
|||
Context("runtime should support seccomp security context", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nits: [security context]
same with other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the top level bucket is "[k8s.io] security context"
This context is for seccomp tests it is already within [k8s.io] security context bucket.
No need to be repeating the phrase security context 2-3 times one at each level in the buckets.
Let me refactor all of the titles making it easier to use focus and skip regexps and only having brackets on the left for ease of reading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@feiskyer On second thought, I also think it is fine to remove the tag given how cri validation test is organized today. :)
Signed-off-by: Mike Brown <[email protected]> adds support for seccomp testing Signed-off-by: Mike Brown <[email protected]>
3c2a89b
to
1590cb7
Compare
@feiskyer I refactored the context container descriptions to fix regexp options and make it easier to read. I also removed repetitive text from the suite descriptions, again to make it easier to read and easier to identify regexp options. Nit addressed. |
@mikebrow thanks 👍 |
/lgtm |
@feiskyer I'm still reviewing. There are issues. :p |
hmm, didn't notice issues. we could open another fix pr for the issues. |
@feiskyer @Random-Liu There was an offline discussion (15min ago) about adding another context to separate docker/default tests. I'll push a pr for that in the morn... |
@@ -225,7 +247,7 @@ var _ = framework.KubeDescribe("Security Context", func() { | |||
}) | |||
}) | |||
|
|||
Context("runtime should support container with security context", func() { | |||
Context("bucket", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by "bucket"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a bucket of tests... This is the second "bucket", bucket-2 would be another possible name. This context is already within the "Security Context" .. the other buckets at this level are NamespaceOption and SeccompProfilePath.
This bucket comprises tests for: SupplementalGroups, RunAsUser, RunAsUserName, ReadOnlyRootfs, Privileged, and Capability. I couldn't come up with a better name for these than the "Security Context bucket"
@@ -402,8 +424,43 @@ var _ = framework.KubeDescribe("Security Context", func() { | |||
|
|||
checkNetworkManagement(rc, containerID, false) | |||
}) | |||
}) | |||
|
|||
Context("SeccompProfilePath", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably just Seccomp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like using the litteral CRI spec name here as it doesn't test all of Seccomp here. It is literally testing the CRI spec defined options for the SeccompProfilePath:
// LinuxSandboxSecurityContext holds linux security configuration that will be
// applied to a sandbox. Note that:
// 1) It does not apply to containers in the pods.
// 2) It may not be applicable to a PodSandbox which does not contain any running
// process.
type LinuxSandboxSecurityContext struct {
// Configurations for the sandbox's namespaces.
// This will be used only if the PodSandbox uses namespace for isolation.
NamespaceOptions *NamespaceOption `protobuf:"bytes,1,opt,name=namespace_options,json=namespaceOptions" json:"namespace_options,omitempty"`
// Optional SELinux context to be applied.
SelinuxOptions *SELinuxOption `protobuf:"bytes,2,opt,name=selinux_options,json=selinuxOptions" json:"selinux_options,omitempty"`
// UID to run sandbox processes as, when applicable.
RunAsUser *Int64Value `protobuf:"bytes,3,opt,name=run_as_user,json=runAsUser" json:"run_as_user,omitempty"`
// If set, the root filesystem of the sandbox is read-only.
ReadonlyRootfs bool `protobuf:"varint,4,opt,name=readonly_rootfs,json=readonlyRootfs,proto3" json:"readonly_rootfs,omitempty"`
// List of groups applied to the first process run in the sandbox, in
// addition to the sandbox's primary GID.
SupplementalGroups []int64 `protobuf:"varint,5,rep,packed,name=supplemental_groups,json=supplementalGroups" json:"supplemental_groups,omitempty"`
// Indicates whether the sandbox will be asked to run a privileged
// container. If a privileged container is to be executed within it, this
// MUST be true.
// This allows a sandbox to take additional security precautions if no
// privileged containers are expected to be run.
Privileged bool `protobuf:"varint,6,opt,name=privileged,proto3" json:"privileged,omitempty"`
// Seccomp profile for the sandbox, candidate values are:
// * docker/default: the default profile for the docker container runtime
// * unconfined: unconfined profile, ie, no seccomp sandboxing
// * localhost/<full-path-to-profile>: the profile installed on the node.
// <full-path-to-profile> is the full path of the profile.
// Default: "", which is identical with unconfined.
SeccompProfilePath string `protobuf:"bytes,7,opt,name=seccomp_profile_path,json=seccompProfilePath,proto3" json:"seccomp_profile_path,omitempty"`
}
@@ -37,6 +38,27 @@ import ( | |||
|
|||
const ( | |||
nginxContainerImage string = "nginx" | |||
localhost string = "localhost/" | |||
// profile which denies sethostname syscall | |||
seccompBlockHostNameProfile = `{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not moving those 2 consts into the Seccomp context. No one else is using it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure I'll move..
|
||
BeforeEach(func() { | ||
profileDir, err = createSeccompProfileDir() | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think we could just log and return, it will still run test then.
You should do assertion here Expect(err).NotTo(HaveOccurred())
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikebrow This is the issue we need to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed will update ..
checkSetHostname(rc, containerID, true) | ||
}) | ||
|
||
It("runtime should block setting hostname with no seccomp profile specified", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no seccomp profile means "unconfined", why set hostname will be blocked? By whom?
Default capabilities? If so, I feel like this is more a capability test instead of seccomp test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WE can add a test to create a default container, and check whether seccomp is enabled. That is useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a duplicate test, I'll delete it.
checkSetHostname(rc, containerID, false) | ||
}) | ||
|
||
It("runtime should support setting hostname with docker/default seccomp profile and sysCaps", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to a separate docker/default
context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we both had that idea at the same time :-)
checkSetHostname(rc, containerID, true) | ||
}) | ||
|
||
It("runtime should block sethostname with docker/default seccomp profile and no sysCaps", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
checkSetHostname(rc, containerID, false) | ||
}) | ||
|
||
It("runtime should block sethostname with nil seccomp profile and no sysCaps", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same. This is a default capability test, not seccomp test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above response to your comments.. maybe we should do a quick call on this.
checkSetHostname(rc, containerID, false) | ||
}) | ||
|
||
It("runtime should block sethostname with unconfined seccomp profile and no sysCaps", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same. This is a default capability test, not seccomp test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's both a default caps test and a seccomp test. See unconfined and default rules below:
// Seccomp profile for the sandbox, candidate values are:
// * docker/default: the default profile for the docker container runtime
// * unconfined: unconfined profile, ie, no seccomp sandboxing
// * localhost/<full-path-to-profile>: the profile installed on the node.
// <full-path-to-profile> is the full path of the profile.
// Default: "", which is identical with unconfined.
SeccompProfilePath string `protobuf:"bytes,7,opt,name=seccomp_profile_path,json=seccompProfilePath,proto3" json:"seccomp_profile_path,omitempty"`
If you have an idea for a better way to test the unconfined and nil SeccompProfilePath options.. I'm all ears :)
@mikebrow Please address the comments. |
Signed-off-by: Mike Brown <[email protected]>
Responding to comments on #137
Adding support for seccomp testing.
Will add pod testing after validating these container tests.
@Random-Liu