Skip to content

Commit 550b494

Browse files
authored
Merge pull request #4700 from mikebrow/cri-security-profile-update
CRI security profile update for CRI graduation
2 parents 3b6a386 + 6467c33 commit 550b494

8 files changed

Lines changed: 1300 additions & 532 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ require (
6262
k8s.io/apiserver v0.19.4
6363
k8s.io/client-go v0.19.4
6464
k8s.io/component-base v0.19.4
65-
k8s.io/cri-api v0.19.4
65+
k8s.io/cri-api v0.20.0-beta.1.0.20201105173512-3990421b69a0
6666
k8s.io/klog/v2 v2.2.0
6767
k8s.io/utils v0.0.0-20200729134348-d5654de09c73
6868
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,8 @@ k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA=
722722
k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI=
723723
k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70=
724724
k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
725-
k8s.io/cri-api v0.19.4 h1:Vc00x5LSSbLBgvj7UAi4kjsv276n4SGX0XlI/pWhG2E=
726-
k8s.io/cri-api v0.19.4/go.mod h1:UN/iU9Ua0iYdDREBXNE9vqCJ7MIh/FW3VIL0d8pw7Fw=
725+
k8s.io/cri-api v0.20.0-beta.1.0.20201105173512-3990421b69a0 h1:/AO/xlTAHFP+ZLhfYMjSUzMsZe9of1fwh1TupXAKzKE=
726+
k8s.io/cri-api v0.20.0-beta.1.0.20201105173512-3990421b69a0/go.mod h1:UN/iU9Ua0iYdDREBXNE9vqCJ7MIh/FW3VIL0d8pw7Fw=
727727
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
728728
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
729729
k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=

pkg/cri/server/container_create_linux.go

Lines changed: 104 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,15 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
306306
}
307307
specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr))
308308

309+
asp := securityContext.GetApparmor()
310+
if asp == nil {
311+
asp, err = generateApparmorSecurityProfile(securityContext.GetApparmorProfile()) // nolint:staticcheck deprecated but we don't want to remove yet
312+
if err != nil {
313+
return nil, errors.Wrap(err, "failed to generate apparmor spec opts")
314+
}
315+
}
309316
apparmorSpecOpts, err := generateApparmorSpecOpts(
310-
securityContext.GetApparmorProfile(),
317+
asp,
311318
securityContext.GetPrivileged(),
312319
c.apparmorEnabled())
313320
if err != nil {
@@ -317,8 +324,17 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
317324
specOpts = append(specOpts, apparmorSpecOpts)
318325
}
319326

327+
ssp := securityContext.GetSeccomp()
328+
if ssp == nil {
329+
ssp, err = generateSeccompSecurityProfile(
330+
securityContext.GetSeccompProfilePath(), // nolint:staticcheck deprecated but we don't want to remove yet
331+
c.config.UnsetSeccompProfile)
332+
if err != nil {
333+
return nil, errors.Wrap(err, "failed to generate seccomp spec opts")
334+
}
335+
}
320336
seccompSpecOpts, err := c.generateSeccompSpecOpts(
321-
securityContext.GetSeccompProfilePath(),
337+
ssp,
322338
securityContext.GetPrivileged(),
323339
c.seccompEnabled())
324340
if err != nil {
@@ -330,77 +346,128 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
330346
return specOpts, nil
331347
}
332348

349+
func generateSeccompSecurityProfile(profilePath string, unsetProfilePath string) (*runtime.SecurityProfile, error) {
350+
if profilePath != "" {
351+
return generateSecurityProfile(profilePath)
352+
}
353+
if unsetProfilePath != "" {
354+
return generateSecurityProfile(unsetProfilePath)
355+
}
356+
return nil, nil
357+
}
358+
func generateApparmorSecurityProfile(profilePath string) (*runtime.SecurityProfile, error) {
359+
if profilePath != "" {
360+
return generateSecurityProfile(profilePath)
361+
}
362+
return nil, nil
363+
}
364+
365+
func generateSecurityProfile(profilePath string) (*runtime.SecurityProfile, error) {
366+
switch profilePath {
367+
case runtimeDefault, dockerDefault, "":
368+
return &runtime.SecurityProfile{
369+
ProfileType: runtime.SecurityProfile_RuntimeDefault,
370+
}, nil
371+
case unconfinedProfile:
372+
return &runtime.SecurityProfile{
373+
ProfileType: runtime.SecurityProfile_Unconfined,
374+
}, nil
375+
default:
376+
// Require and Trim default profile name prefix
377+
if !strings.HasPrefix(profilePath, profileNamePrefix) {
378+
return nil, errors.Errorf("invalid profile %q", profilePath)
379+
}
380+
return &runtime.SecurityProfile{
381+
ProfileType: runtime.SecurityProfile_Localhost,
382+
LocalhostRef: strings.TrimPrefix(profilePath, profileNamePrefix),
383+
}, nil
384+
}
385+
}
386+
333387
// generateSeccompSpecOpts generates containerd SpecOpts for seccomp.
334-
func (c *criService) generateSeccompSpecOpts(seccompProf string, privileged, seccompEnabled bool) (oci.SpecOpts, error) {
388+
func (c *criService) generateSeccompSpecOpts(sp *runtime.SecurityProfile, privileged, seccompEnabled bool) (oci.SpecOpts, error) {
335389
if privileged {
336390
// Do not set seccomp profile when container is privileged
337391
return nil, nil
338392
}
339-
if seccompProf == "" {
340-
seccompProf = c.config.UnsetSeccompProfile
341-
}
342-
// Set seccomp profile
343-
if seccompProf == runtimeDefault || seccompProf == dockerDefault {
344-
// use correct default profile (Eg. if not configured otherwise, the default is docker/default)
345-
seccompProf = seccompDefaultProfile
346-
}
347393
if !seccompEnabled {
348-
if seccompProf != "" && seccompProf != unconfinedProfile {
349-
return nil, errors.New("seccomp is not supported")
394+
if sp != nil {
395+
if sp.ProfileType != runtime.SecurityProfile_Unconfined {
396+
return nil, errors.New("seccomp is not supported")
397+
}
350398
}
351399
return nil, nil
352400
}
353-
switch seccompProf {
354-
case "", unconfinedProfile:
401+
402+
if sp == nil {
403+
return nil, nil
404+
}
405+
406+
if sp.ProfileType != runtime.SecurityProfile_Localhost && sp.LocalhostRef != "" {
407+
return nil, errors.New("seccomp config invalid LocalhostRef must only be set if ProfileType is Localhost")
408+
}
409+
switch sp.ProfileType {
410+
case runtime.SecurityProfile_Unconfined:
355411
// Do not set seccomp profile.
356412
return nil, nil
357-
case dockerDefault:
358-
// Note: WithDefaultProfile specOpts must be added after capabilities
413+
case runtime.SecurityProfile_RuntimeDefault:
359414
return seccomp.WithDefaultProfile(), nil
415+
case runtime.SecurityProfile_Localhost:
416+
// trimming the localhost/ prefix just in case even though it should not
417+
// be necessary with the new SecurityProfile struct
418+
return seccomp.WithProfile(strings.TrimPrefix(sp.LocalhostRef, profileNamePrefix)), nil
360419
default:
361-
// Require and Trim default profile name prefix
362-
if !strings.HasPrefix(seccompProf, profileNamePrefix) {
363-
return nil, errors.Errorf("invalid seccomp profile %q", seccompProf)
364-
}
365-
return seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)), nil
420+
return nil, errors.New("seccomp unknown ProfileType")
366421
}
367422
}
368423

369424
// generateApparmorSpecOpts generates containerd SpecOpts for apparmor.
370-
func generateApparmorSpecOpts(apparmorProf string, privileged, apparmorEnabled bool) (oci.SpecOpts, error) {
425+
func generateApparmorSpecOpts(sp *runtime.SecurityProfile, privileged, apparmorEnabled bool) (oci.SpecOpts, error) {
371426
if !apparmorEnabled {
372427
// Should fail loudly if user try to specify apparmor profile
373428
// but we don't support it.
374-
if apparmorProf != "" && apparmorProf != unconfinedProfile {
375-
return nil, errors.New("apparmor is not supported")
429+
if sp != nil {
430+
if sp.ProfileType != runtime.SecurityProfile_Unconfined {
431+
return nil, errors.New("apparmor is not supported")
432+
}
376433
}
377434
return nil, nil
378435
}
379-
switch apparmorProf {
380-
// Based on kubernetes#51746, default apparmor profile should be applied
381-
// for when apparmor is not specified.
382-
case runtimeDefault, "":
436+
437+
if sp == nil {
438+
// Based on kubernetes#51746, default apparmor profile should be applied
439+
// for when apparmor is not specified.
440+
sp, _ = generateSecurityProfile("")
441+
}
442+
443+
if sp.ProfileType != runtime.SecurityProfile_Localhost && sp.LocalhostRef != "" {
444+
return nil, errors.New("apparmor config invalid LocalhostRef must only be set if ProfileType is Localhost")
445+
}
446+
447+
switch sp.ProfileType {
448+
case runtime.SecurityProfile_Unconfined:
449+
// Do not set apparmor profile.
450+
return nil, nil
451+
case runtime.SecurityProfile_RuntimeDefault:
383452
if privileged {
384453
// Do not set apparmor profile when container is privileged
385454
return nil, nil
386455
}
387456
// TODO (mikebrow): delete created apparmor default profile
388457
return apparmor.WithDefaultProfile(appArmorDefaultProfileName), nil
389-
case unconfinedProfile:
390-
return nil, nil
391-
default:
392-
// Require and Trim default profile name prefix
393-
if !strings.HasPrefix(apparmorProf, profileNamePrefix) {
394-
return nil, errors.Errorf("invalid apparmor profile %q", apparmorProf)
395-
}
396-
appArmorProfile := strings.TrimPrefix(apparmorProf, profileNamePrefix)
458+
case runtime.SecurityProfile_Localhost:
459+
// trimming the localhost/ prefix just in case even through it should not
460+
// be necessary with the new SecurityProfile struct
461+
appArmorProfile := strings.TrimPrefix(sp.LocalhostRef, profileNamePrefix)
397462
if profileExists, err := appArmorProfileExists(appArmorProfile); !profileExists {
398463
if err != nil {
399464
return nil, errors.Wrap(err, "failed to generate apparmor spec opts")
400465
}
401466
return nil, errors.Errorf("apparmor profile not found %s", appArmorProfile)
402467
}
403468
return apparmor.WithProfile(appArmorProfile), nil
469+
default:
470+
return nil, errors.New("apparmor unknown ProfileType")
404471
}
405472
}
406473

0 commit comments

Comments
 (0)