kubelet: Use CRI SecurityProfile for Seccomp
We set both the old and the new fields for now and will remove the old field in the next release. Signed-off-by: Mrunal Patel <mpatel@redhat.com>
This commit is contained in:
parent
fe48ad8d22
commit
32b9ac7d0c
@ -228,7 +228,7 @@ func annotationProfile(profile, profileRootPath string) string {
|
|||||||
return profile
|
return profile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *kubeGenericRuntimeManager) getSeccompProfile(annotations map[string]string, containerName string,
|
func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string]string, containerName string,
|
||||||
podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext) string {
|
podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext) string {
|
||||||
// container fields are applied first
|
// container fields are applied first
|
||||||
if containerSecContext != nil && containerSecContext.SeccompProfile != nil {
|
if containerSecContext != nil && containerSecContext.SeccompProfile != nil {
|
||||||
@ -255,6 +255,48 @@ func (m *kubeGenericRuntimeManager) getSeccompProfile(annotations map[string]str
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldSeccompProfile(scmp *v1.SeccompProfile, profileRootPath string) *runtimeapi.SecurityProfile {
|
||||||
|
// TODO: Move to RuntimeDefault as the default instead of Unconfined after discussion
|
||||||
|
// with sig-node.
|
||||||
|
if scmp == nil {
|
||||||
|
return &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Unconfined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scmp.Type == v1.SeccompProfileTypeRuntimeDefault {
|
||||||
|
return &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_RuntimeDefault,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scmp.Type == v1.SeccompProfileTypeLocalhost && scmp.LocalhostProfile != nil && len(*scmp.LocalhostProfile) > 0 {
|
||||||
|
fname := filepath.Join(profileRootPath, *scmp.LocalhostProfile)
|
||||||
|
return &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Localhost,
|
||||||
|
LocalhostRef: fname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Unconfined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *kubeGenericRuntimeManager) getSeccompProfile(annotations map[string]string, containerName string,
|
||||||
|
podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext) *runtimeapi.SecurityProfile {
|
||||||
|
// container fields are applied first
|
||||||
|
if containerSecContext != nil && containerSecContext.SeccompProfile != nil {
|
||||||
|
return fieldSeccompProfile(containerSecContext.SeccompProfile, m.seccompProfileRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
// when container seccomp is not defined, try to apply from pod field
|
||||||
|
if podSecContext != nil && podSecContext.SeccompProfile != nil {
|
||||||
|
return fieldSeccompProfile(podSecContext.SeccompProfile, m.seccompProfileRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Unconfined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ipcNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode {
|
func ipcNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode {
|
||||||
if pod != nil && pod.Spec.HostIPC {
|
if pod != nil && pod.Spec.HostIPC {
|
||||||
return runtimeapi.NamespaceMode_NODE
|
return runtimeapi.NamespaceMode_NODE
|
||||||
|
@ -226,7 +226,7 @@ func TestFieldProfile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSeccompProfile(t *testing.T) {
|
func TestGetSeccompProfilePath(t *testing.T) {
|
||||||
_, _, m, err := createTestRuntimeManager()
|
_, _, m, err := createTestRuntimeManager()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -410,6 +410,100 @@ func TestGetSeccompProfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
seccompProfile := m.getSeccompProfilePath(test.annotation, test.containerName, test.podSc, test.containerSc)
|
||||||
|
assert.Equal(t, test.expectedProfile, seccompProfile, "TestCase[%d]: %s", i, test.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSeccompProfile(t *testing.T) {
|
||||||
|
_, _, m, err := createTestRuntimeManager()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
unconfinedProfile := &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Unconfined,
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeDefaultProfile := &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_RuntimeDefault,
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
annotation map[string]string
|
||||||
|
podSc *v1.PodSecurityContext
|
||||||
|
containerSc *v1.SecurityContext
|
||||||
|
containerName string
|
||||||
|
expectedProfile *runtimeapi.SecurityProfile
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "no seccomp should return unconfined",
|
||||||
|
expectedProfile: unconfinedProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod seccomp profile set to unconfined returns unconfined",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}},
|
||||||
|
expectedProfile: unconfinedProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "container seccomp profile set to unconfined returns unconfined",
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}},
|
||||||
|
expectedProfile: unconfinedProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod seccomp profile set to SeccompProfileTypeRuntimeDefault returns runtime/default",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}},
|
||||||
|
expectedProfile: runtimeDefaultProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "container seccomp profile set to SeccompProfileTypeRuntimeDefault returns runtime/default",
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}},
|
||||||
|
expectedProfile: runtimeDefaultProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("filename")}},
|
||||||
|
expectedProfile: &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Localhost,
|
||||||
|
LocalhostRef: filepath.Join(fakeSeccompProfileRoot, "filename"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod seccomp profile set to SeccompProfileTypeLocalhost with empty LocalhostProfile returns unconfined",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost}},
|
||||||
|
expectedProfile: unconfinedProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "container seccomp profile set to SeccompProfileTypeLocalhost with empty LocalhostProfile returns unconfined",
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost}},
|
||||||
|
expectedProfile: unconfinedProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "container seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile",
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("filename2")}},
|
||||||
|
expectedProfile: &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Localhost,
|
||||||
|
LocalhostRef: filepath.Join(fakeSeccompProfileRoot, "filename2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "prioritise container field over pod field",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}},
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}},
|
||||||
|
expectedProfile: runtimeDefaultProfile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "prioritise container field over pod field",
|
||||||
|
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
|
||||||
|
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-cont-profile.json")}},
|
||||||
|
containerName: "container1",
|
||||||
|
expectedProfile: &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_Localhost,
|
||||||
|
LocalhostRef: filepath.Join(fakeSeccompProfileRoot, "field-cont-profile.json"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
seccompProfile := m.getSeccompProfile(test.annotation, test.containerName, test.podSc, test.containerSc)
|
seccompProfile := m.getSeccompProfile(test.annotation, test.containerName, test.podSc, test.containerSc)
|
||||||
assert.Equal(t, test.expectedProfile, seccompProfile, "TestCase[%d]: %s", i, test.description)
|
assert.Equal(t, test.expectedProfile, seccompProfile, "TestCase[%d]: %s", i, test.description)
|
||||||
|
@ -154,9 +154,14 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) (
|
|||||||
SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{
|
SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{
|
||||||
Privileged: kubecontainer.HasPrivilegedContainer(pod),
|
Privileged: kubecontainer.HasPrivilegedContainer(pod),
|
||||||
|
|
||||||
|
// TODO: Deprecated, remove after we switch to Seccomp field
|
||||||
// Forcing sandbox to run as `runtime/default` allow users to
|
// Forcing sandbox to run as `runtime/default` allow users to
|
||||||
// use least privileged seccomp profiles at pod level. Issue #84623
|
// use least privileged seccomp profiles at pod level. Issue #84623
|
||||||
SeccompProfilePath: v1.SeccompProfileRuntimeDefault,
|
SeccompProfilePath: v1.SeccompProfileRuntimeDefault,
|
||||||
|
|
||||||
|
Seccomp: &runtimeapi.SecurityProfile{
|
||||||
|
ProfileType: runtimeapi.SecurityProfile_RuntimeDefault,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,11 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Deprecated, remove after we switch to Seccomp field
|
||||||
// set SeccompProfilePath.
|
// set SeccompProfilePath.
|
||||||
synthesized.SeccompProfilePath = m.getSeccompProfile(pod.Annotations, container.Name, pod.Spec.SecurityContext, container.SecurityContext)
|
synthesized.SeccompProfilePath = m.getSeccompProfilePath(pod.Annotations, container.Name, pod.Spec.SecurityContext, container.SecurityContext)
|
||||||
|
|
||||||
|
synthesized.Seccomp = m.getSeccompProfile(pod.Annotations, container.Name, pod.Spec.SecurityContext, container.SecurityContext)
|
||||||
|
|
||||||
// set ApparmorProfile.
|
// set ApparmorProfile.
|
||||||
synthesized.ApparmorProfile = apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
|
synthesized.ApparmorProfile = apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
|
||||||
|
Loading…
Reference in New Issue
Block a user