Merge pull request #89225 from andrewsykim/apparmor-api

move apparmor annotation constants to k8s.io/api/core/v1
This commit is contained in:
Kubernetes Prow Robot 2020-04-12 19:11:50 -07:00 committed by GitHub
commit 6239abe698
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 131 additions and 147 deletions

View File

@ -13,7 +13,7 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
@ -39,7 +39,7 @@ go_test(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",

View File

@ -19,11 +19,11 @@ package pod
import (
"strings"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/security/apparmor"
)
// ContainerType signifies container type
@ -363,7 +363,7 @@ func dropDisabledFields(
if !utilfeature.DefaultFeatureGate.Enabled(features.AppArmor) && !appArmorInUse(oldPodAnnotations) {
for k := range podAnnotations {
if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
delete(podAnnotations, k)
}
}
@ -590,7 +590,7 @@ func procMountInUse(podSpec *api.PodSpec) bool {
// appArmorInUse returns true if the pod has apparmor related information
func appArmorInUse(podAnnotations map[string]string) bool {
for k := range podAnnotations {
if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
return true
}
}

View File

@ -23,6 +23,8 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
@ -32,7 +34,6 @@ import (
featuregatetesting "k8s.io/component-base/featuregate/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/security/apparmor"
)
func TestVisitContainers(t *testing.T) {
@ -1026,7 +1027,7 @@ func TestDropEmptyDirSizeLimit(t *testing.T) {
func TestDropAppArmor(t *testing.T) {
podWithAppArmor := func() *api.Pod {
return &api.Pod{
ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{"a": "1", apparmor.ContainerAnnotationKeyPrefix + "foo": "default"}},
ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{"a": "1", v1.AppArmorBetaContainerAnnotationKeyPrefix + "foo": "default"}},
Spec: api.PodSpec{},
}
}

View File

@ -56,7 +56,6 @@ go_test(
"//pkg/apis/core:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@ -173,7 +173,7 @@ func ValidatePodSpecificAnnotationUpdates(newPod, oldPod *core.Pod, fldPath *fie
if newVal, exists := newAnnotations[k]; exists && newVal == oldVal {
continue // No change.
}
if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
allErrs = append(allErrs, field.Forbidden(fldPath.Key(k), "may not remove or update AppArmor annotations"))
}
if k == core.MirrorPodAnnotationKey {
@ -185,7 +185,7 @@ func ValidatePodSpecificAnnotationUpdates(newPod, oldPod *core.Pod, fldPath *fie
if _, ok := oldAnnotations[k]; ok {
continue // No change.
}
if strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
if strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
allErrs = append(allErrs, field.Forbidden(fldPath.Key(k), "may not add AppArmor annotations"))
}
if k == core.MirrorPodAnnotationKey {
@ -3572,10 +3572,10 @@ func ValidateSeccompPodAnnotations(annotations map[string]string, fldPath *field
func ValidateAppArmorPodAnnotations(annotations map[string]string, spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for k, p := range annotations {
if !strings.HasPrefix(k, apparmor.ContainerAnnotationKeyPrefix) {
if !strings.HasPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
continue
}
containerName := strings.TrimPrefix(k, apparmor.ContainerAnnotationKeyPrefix)
containerName := strings.TrimPrefix(k, v1.AppArmorBetaContainerAnnotationKeyPrefix)
if !podSpecHasContainer(spec, containerName) {
allErrs = append(allErrs, field.Invalid(fldPath.Key(k), containerName, "container not found"))
}

View File

@ -35,7 +35,6 @@ import (
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/security/apparmor"
utilpointer "k8s.io/utils/pointer"
)
@ -7293,7 +7292,7 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "ctr": apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "ctr": v1.AppArmorBetaProfileRuntimeDefault,
},
},
Spec: validPodSpec(nil),
@ -7303,7 +7302,7 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "init-ctr": apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "init-ctr": v1.AppArmorBetaProfileRuntimeDefault,
},
},
Spec: core.PodSpec{
@ -7318,7 +7317,7 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "ctr": apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaContainerAnnotationKeyPrefix + "ctr": v1.AppArmorBetaProfileNamePrefix + "foo",
},
},
Spec: validPodSpec(nil),
@ -8017,9 +8016,9 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "ctr": apparmor.ProfileRuntimeDefault,
apparmor.ContainerAnnotationKeyPrefix + "init-ctr": apparmor.ProfileRuntimeDefault,
apparmor.ContainerAnnotationKeyPrefix + "fake-ctr": apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "ctr": v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "init-ctr": v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "fake-ctr": v1.AppArmorBetaProfileRuntimeDefault,
},
},
Spec: core.PodSpec{
@ -8037,7 +8036,7 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "ctr": "bad-name",
v1.AppArmorBetaContainerAnnotationKeyPrefix + "ctr": "bad-name",
},
},
Spec: validPodSpec(nil),
@ -8050,7 +8049,7 @@ func TestValidatePod(t *testing.T) {
Name: "123",
Namespace: "ns",
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "ctr": "runtime/foo",
v1.AppArmorBetaContainerAnnotationKeyPrefix + "ctr": "runtime/foo",
},
},
Spec: validPodSpec(nil),

View File

@ -18,6 +18,7 @@ go_library(
"//pkg/security/apparmor:go_default_library",
"//pkg/security/podsecuritypolicy/seccomp:go_default_library",
"//pkg/security/podsecuritypolicy/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
@ -32,9 +33,9 @@ go_test(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/security/podsecuritypolicy/seccomp:go_default_library",
"//pkg/security/podsecuritypolicy/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",

View File

@ -22,6 +22,7 @@ import (
"regexp"
"strings"
"k8s.io/api/core/v1"
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/util/sets"
@ -129,15 +130,15 @@ func ValidatePodSecurityPolicySpec(spec *policy.PodSecurityPolicySpec, fldPath *
func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" {
if p := annotations[v1.AppArmorBetaDefaultProfileAnnotationKey]; p != "" {
if err := apparmor.ValidateProfileFormat(p); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error()))
allErrs = append(allErrs, field.Invalid(fldPath.Key(v1.AppArmorBetaDefaultProfileAnnotationKey), p, err.Error()))
}
}
if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" {
if allowed := annotations[v1.AppArmorBetaAllowedProfilesAnnotationKey]; allowed != "" {
for _, p := range strings.Split(allowed, ",") {
if err := apparmor.ValidateProfileFormat(p); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error()))
allErrs = append(allErrs, field.Invalid(fldPath.Key(v1.AppArmorBetaAllowedProfilesAnnotationKey), allowed, err.Error()))
}
}
}

View File

@ -21,12 +21,12 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation/field"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/security/apparmor"
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
"k8s.io/utils/pointer"
@ -223,11 +223,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
invalidAppArmorDefault := validPSP()
invalidAppArmorDefault.Annotations = map[string]string{
apparmor.DefaultProfileAnnotationKey: "not-good",
v1.AppArmorBetaDefaultProfileAnnotationKey: "not-good",
}
invalidAppArmorAllowed := validPSP()
invalidAppArmorAllowed.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + ",not-good",
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault + ",not-good",
}
invalidAllowedUnsafeSysctlPattern := validPSP()
@ -521,8 +521,8 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
validAppArmor := validPSP()
validAppArmor.Annotations = map[string]string{
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault + "," + v1.AppArmorBetaProfileNamePrefix + "foo",
}
withForbiddenSysctl := validPSP()

View File

@ -55,7 +55,6 @@ go_library(
"//pkg/kubelet/types:go_default_library",
"//pkg/kubelet/util/cache:go_default_library",
"//pkg/kubelet/util/ioutils:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/util/parsers:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -111,7 +110,7 @@ go_test(
"//pkg/kubelet/dockershim/network/testing:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//pkg/kubelet/util/cache:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
"//staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2:go_default_library",
"//vendor/github.com/blang/semver:go_default_library",
@ -123,12 +122,6 @@ go_test(
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"//staging/src/k8s.io/api/core/v1:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//staging/src/k8s.io/api/core/v1:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows/registry:go_default_library",
],

View File

@ -31,12 +31,12 @@ import (
dockernat "github.com/docker/go-connections/nat"
"k8s.io/klog"
"k8s.io/api/core/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"k8s.io/kubernetes/pkg/credentialprovider"
"k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker"
"k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/security/apparmor"
"k8s.io/kubernetes/pkg/util/parsers"
)
@ -361,18 +361,18 @@ func ensureSandboxImageExists(client libdocker.Interface, image string) error {
}
func getAppArmorOpts(profile string) ([]dockerOpt, error) {
if profile == "" || profile == apparmor.ProfileRuntimeDefault {
if profile == "" || profile == v1.AppArmorBetaProfileRuntimeDefault {
// The docker applies the default profile by default.
return nil, nil
}
// Return unconfined profile explicitly
if profile == apparmor.ProfileNameUnconfined {
return []dockerOpt{{"apparmor", apparmor.ProfileNameUnconfined, ""}}, nil
if profile == v1.AppArmorBetaProfileNameUnconfined {
return []dockerOpt{{"apparmor", v1.AppArmorBetaProfileNameUnconfined, ""}}, nil
}
// Assume validation has already happened.
profileName := strings.TrimPrefix(profile, apparmor.ProfileNamePrefix)
profileName := strings.TrimPrefix(profile, v1.AppArmorBetaProfileNamePrefix)
return []dockerOpt{{"apparmor", profileName, ""}}, nil
}

View File

@ -28,9 +28,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/api/core/v1"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker"
"k8s.io/kubernetes/pkg/security/apparmor"
)
func TestLabelsAndAnnotationsRoundTrip(t *testing.T) {
@ -66,7 +66,7 @@ func TestGetApparmorSecurityOpts(t *testing.T) {
expectedOpts: []string{},
}, {
msg: "AppArmor local profile",
config: makeConfig(apparmor.ProfileNamePrefix + "foo"),
config: makeConfig(v1.AppArmorBetaProfileNamePrefix + "foo"),
expectedOpts: []string{"apparmor=foo"},
}}

View File

@ -22,29 +22,11 @@ import (
"k8s.io/api/core/v1"
)
// TODO: Move these values into the API package.
const (
// The prefix to an annotation key specifying a container profile.
ContainerAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/"
// The annotation key specifying the default AppArmor profile.
DefaultProfileAnnotationKey = "apparmor.security.beta.kubernetes.io/defaultProfileName"
// The annotation key specifying the allowed AppArmor profiles.
AllowedProfilesAnnotationKey = "apparmor.security.beta.kubernetes.io/allowedProfileNames"
// The profile specifying the runtime default.
ProfileRuntimeDefault = "runtime/default"
// The prefix for specifying profiles loaded on the node.
ProfileNamePrefix = "localhost/"
// Unconfined profile
ProfileNameUnconfined = "unconfined"
)
// Checks whether app armor is required for pod to be run.
func isRequired(pod *v1.Pod) bool {
for key, value := range pod.Annotations {
if strings.HasPrefix(key, ContainerAnnotationKeyPrefix) {
return value != ProfileNameUnconfined
if strings.HasPrefix(key, v1.AppArmorBetaContainerAnnotationKeyPrefix) {
return value != v1.AppArmorBetaProfileNameUnconfined
}
}
return false
@ -58,7 +40,7 @@ func GetProfileName(pod *v1.Pod, containerName string) string {
// GetProfileNameFromPodAnnotations gets the name of the profile to use with container from
// pod annotations
func GetProfileNameFromPodAnnotations(annotations map[string]string, containerName string) string {
return annotations[ContainerAnnotationKeyPrefix+containerName]
return annotations[v1.AppArmorBetaContainerAnnotationKeyPrefix+containerName]
}
// SetProfileName sets the name of the profile to use with the container.
@ -66,7 +48,7 @@ func SetProfileName(pod *v1.Pod, containerName, profileName string) error {
if pod.Annotations == nil {
pod.Annotations = map[string]string{}
}
pod.Annotations[ContainerAnnotationKeyPrefix+containerName] = profileName
pod.Annotations[v1.AppArmorBetaContainerAnnotationKeyPrefix+containerName] = profileName
return nil
}
@ -75,6 +57,6 @@ func SetProfileNameFromPodAnnotations(annotations map[string]string, containerNa
if annotations == nil {
return nil
}
annotations[ContainerAnnotationKeyPrefix+containerName] = profileName
annotations[v1.AppArmorBetaContainerAnnotationKeyPrefix+containerName] = profileName
return nil
}

View File

@ -125,8 +125,8 @@ func validateProfile(profile string, loadedProfiles map[string]bool) error {
return err
}
if strings.HasPrefix(profile, ProfileNamePrefix) {
profileName := strings.TrimPrefix(profile, ProfileNamePrefix)
if strings.HasPrefix(profile, v1.AppArmorBetaProfileNamePrefix) {
profileName := strings.TrimPrefix(profile, v1.AppArmorBetaProfileNamePrefix)
if !loadedProfiles[profileName] {
return fmt.Errorf("profile %q is not loaded", profileName)
}
@ -137,10 +137,10 @@ func validateProfile(profile string, loadedProfiles map[string]bool) error {
// ValidateProfileFormat checks the format of the profile.
func ValidateProfileFormat(profile string) error {
if profile == "" || profile == ProfileRuntimeDefault || profile == ProfileNameUnconfined {
if profile == "" || profile == v1.AppArmorBetaProfileRuntimeDefault || profile == v1.AppArmorBetaProfileNameUnconfined {
return nil
}
if !strings.HasPrefix(profile, ProfileNamePrefix) {
if !strings.HasPrefix(profile, v1.AppArmorBetaProfileNamePrefix) {
return fmt.Errorf("invalid AppArmor profile name: %q", profile)
}
return nil

View File

@ -62,13 +62,13 @@ func TestValidateProfile(t *testing.T) {
expectValid bool
}{
{"", true},
{ProfileRuntimeDefault, true},
{ProfileNameUnconfined, true},
{v1.AppArmorBetaProfileRuntimeDefault, true},
{v1.AppArmorBetaProfileNameUnconfined, true},
{"baz", false}, // Missing local prefix.
{ProfileNamePrefix + "/usr/sbin/ntpd", true},
{ProfileNamePrefix + "foo-bar", true},
{ProfileNamePrefix + "unloaded", false}, // Not loaded.
{ProfileNamePrefix + "", false},
{v1.AppArmorBetaProfileNamePrefix + "/usr/sbin/ntpd", true},
{v1.AppArmorBetaProfileNamePrefix + "foo-bar", true},
{v1.AppArmorBetaProfileNamePrefix + "unloaded", false}, // Not loaded.
{v1.AppArmorBetaProfileNamePrefix + "", false},
}
for _, test := range tests {
@ -92,8 +92,8 @@ func TestValidateBadHost(t *testing.T) {
expectValid bool
}{
{"", true},
{ProfileRuntimeDefault, false},
{ProfileNamePrefix + "docker-default", false},
{v1.AppArmorBetaProfileRuntimeDefault, false},
{v1.AppArmorBetaProfileNamePrefix + "docker-default", false},
}
for _, test := range tests {
@ -116,13 +116,13 @@ func TestValidateValidHost(t *testing.T) {
expectValid bool
}{
{"", true},
{ProfileRuntimeDefault, true},
{ProfileNamePrefix + "docker-default", true},
{ProfileNamePrefix + "foo-container", true},
{ProfileNamePrefix + "/usr/sbin/ntpd", true},
{v1.AppArmorBetaProfileRuntimeDefault, true},
{v1.AppArmorBetaProfileNamePrefix + "docker-default", true},
{v1.AppArmorBetaProfileNamePrefix + "foo-container", true},
{v1.AppArmorBetaProfileNamePrefix + "/usr/sbin/ntpd", true},
{"docker-default", false},
{ProfileNamePrefix + "foo", false},
{ProfileNamePrefix + "", false},
{v1.AppArmorBetaProfileNamePrefix + "foo", false},
{v1.AppArmorBetaProfileNamePrefix + "", false},
}
for _, test := range tests {
@ -138,9 +138,9 @@ func TestValidateValidHost(t *testing.T) {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
ContainerAnnotationKeyPrefix + "init": ProfileNamePrefix + "foo-container",
ContainerAnnotationKeyPrefix + "test1": ProfileRuntimeDefault,
ContainerAnnotationKeyPrefix + "test2": ProfileNamePrefix + "docker-default",
v1.AppArmorBetaContainerAnnotationKeyPrefix + "init": v1.AppArmorBetaProfileNamePrefix + "foo-container",
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test1": v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test2": v1.AppArmorBetaProfileNamePrefix + "docker-default",
},
},
Spec: v1.PodSpec{
@ -176,7 +176,7 @@ func TestParseProfileName(t *testing.T) {
func getPodWithProfile(profile string) *v1.Pod {
annotations := map[string]string{
ContainerAnnotationKeyPrefix + "test": profile,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test": profile,
}
if profile == "" {
annotations = map[string]string{

View File

@ -14,6 +14,7 @@ go_library(
"//pkg/apis/core:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/util/maps:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
@ -24,8 +25,8 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/util/maps:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -20,6 +20,7 @@ import (
"fmt"
"strings"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/security/apparmor"
@ -47,7 +48,7 @@ var _ Strategy = &strategy{}
// NewStrategy creates a new strategy that enforces AppArmor profile constraints.
func NewStrategy(pspAnnotations map[string]string) Strategy {
var allowedProfiles map[string]bool
if allowed, ok := pspAnnotations[apparmor.AllowedProfilesAnnotationKey]; ok {
if allowed, ok := pspAnnotations[v1.AppArmorBetaAllowedProfilesAnnotationKey]; ok {
profiles := strings.Split(allowed, ",")
allowedProfiles = make(map[string]bool, len(profiles))
for _, p := range profiles {
@ -55,16 +56,16 @@ func NewStrategy(pspAnnotations map[string]string) Strategy {
}
}
return &strategy{
defaultProfile: pspAnnotations[apparmor.DefaultProfileAnnotationKey],
defaultProfile: pspAnnotations[v1.AppArmorBetaDefaultProfileAnnotationKey],
allowedProfiles: allowedProfiles,
allowedProfilesString: pspAnnotations[apparmor.AllowedProfilesAnnotationKey],
allowedProfilesString: pspAnnotations[v1.AppArmorBetaAllowedProfilesAnnotationKey],
}
}
func (s *strategy) Generate(annotations map[string]string, container *api.Container) (map[string]string, error) {
copy := maps.CopySS(annotations)
if annotations[apparmor.ContainerAnnotationKeyPrefix+container.Name] != "" {
if annotations[v1.AppArmorBetaContainerAnnotationKeyPrefix+container.Name] != "" {
// Profile already set, nothing to do.
return copy, nil
}
@ -78,7 +79,7 @@ func (s *strategy) Generate(annotations map[string]string, container *api.Contai
copy = map[string]string{}
}
// Add the default profile.
copy[apparmor.ContainerAnnotationKeyPrefix+container.Name] = s.defaultProfile
copy[v1.AppArmorBetaContainerAnnotationKeyPrefix+container.Name] = s.defaultProfile
return copy, nil
}
@ -90,7 +91,7 @@ func (s *strategy) Validate(pod *api.Pod, container *api.Container) field.ErrorL
}
allErrs := field.ErrorList{}
fieldPath := field.NewPath("pod", "metadata", "annotations").Key(apparmor.ContainerAnnotationKeyPrefix + container.Name)
fieldPath := field.NewPath("pod", "metadata", "annotations").Key(v1.AppArmorBetaContainerAnnotationKeyPrefix + container.Name)
profile := apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
if profile == "" {

View File

@ -22,9 +22,9 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/stretchr/testify/assert"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/security/apparmor"
"k8s.io/kubernetes/pkg/util/maps"
)
@ -36,29 +36,29 @@ var (
withoutAppArmor = map[string]string{"foo": "bar"}
withDefault = map[string]string{
"foo": "bar",
apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + containerName: v1.AppArmorBetaProfileRuntimeDefault,
}
withLocal = map[string]string{
"foo": "bar",
apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaContainerAnnotationKeyPrefix + containerName: v1.AppArmorBetaProfileNamePrefix + "foo",
}
withDisallowed = map[string]string{
"foo": "bar",
apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileNamePrefix + "bad",
v1.AppArmorBetaContainerAnnotationKeyPrefix + containerName: v1.AppArmorBetaProfileNamePrefix + "bad",
}
noAppArmor = map[string]string{"foo": "bar"}
unconstrainedWithDefault = map[string]string{
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
}
constrained = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," +
apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault + "," +
v1.AppArmorBetaProfileNamePrefix + "foo",
}
constrainedWithDefault = map[string]string{
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," +
apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault + "," +
v1.AppArmorBetaProfileNamePrefix + "foo",
}
container = api.Container{

View File

@ -546,13 +546,13 @@ func TestValidateContainerFailures(t *testing.T) {
failNilAppArmorPod := defaultPod()
v1FailInvalidAppArmorPod := defaultV1Pod()
apparmor.SetProfileName(v1FailInvalidAppArmorPod, defaultContainerName, apparmor.ProfileNamePrefix+"foo")
apparmor.SetProfileName(v1FailInvalidAppArmorPod, defaultContainerName, v1.AppArmorBetaProfileNamePrefix+"foo")
failInvalidAppArmorPod := &api.Pod{}
k8s_api_v1.Convert_v1_Pod_To_core_Pod(v1FailInvalidAppArmorPod, failInvalidAppArmorPod, nil)
failAppArmorPSP := defaultPSP()
failAppArmorPSP.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
}
failPrivPod := defaultPod()
@ -1033,10 +1033,10 @@ func TestValidateContainerSuccess(t *testing.T) {
appArmorPSP := defaultPSP()
appArmorPSP.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
}
v1AppArmorPod := defaultV1Pod()
apparmor.SetProfileName(v1AppArmorPod, defaultContainerName, apparmor.ProfileRuntimeDefault)
apparmor.SetProfileName(v1AppArmorPod, defaultContainerName, v1.AppArmorBetaProfileRuntimeDefault)
appArmorPod := &api.Pod{}
k8s_api_v1.Convert_v1_Pod_To_core_Pod(v1AppArmorPod, appArmorPod, nil)

View File

@ -1115,16 +1115,16 @@ func TestAdmitAppArmor(t *testing.T) {
unconstrainedPSP := restrictivePSP()
defaultedPSP := restrictivePSP()
defaultedPSP.Annotations = map[string]string{
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
}
appArmorPSP := restrictivePSP()
appArmorPSP.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
}
appArmorDefaultPSP := restrictivePSP()
appArmorDefaultPSP.Annotations = map[string]string{
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault + "," + apparmor.ProfileNamePrefix + "foo",
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault + "," + v1.AppArmorBetaProfileNamePrefix + "foo",
}
tests := map[string]struct {
@ -1142,18 +1142,18 @@ func TestAdmitAppArmor(t *testing.T) {
expectedProfile: "",
},
"unconstrained with profile": {
pod: createPodWithAppArmor(apparmor.ProfileRuntimeDefault),
pod: createPodWithAppArmor(v1.AppArmorBetaProfileRuntimeDefault),
psp: unconstrainedPSP,
shouldPassAdmit: true,
shouldPassValidate: true,
expectedProfile: apparmor.ProfileRuntimeDefault,
expectedProfile: v1.AppArmorBetaProfileRuntimeDefault,
},
"unconstrained with default profile": {
pod: goodPod(),
psp: defaultedPSP,
shouldPassAdmit: true,
shouldPassValidate: true,
expectedProfile: apparmor.ProfileRuntimeDefault,
expectedProfile: v1.AppArmorBetaProfileRuntimeDefault,
},
"AppArmor enforced with no profile": {
pod: goodPod(),
@ -1166,17 +1166,17 @@ func TestAdmitAppArmor(t *testing.T) {
psp: appArmorDefaultPSP,
shouldPassAdmit: true,
shouldPassValidate: true,
expectedProfile: apparmor.ProfileRuntimeDefault,
expectedProfile: v1.AppArmorBetaProfileRuntimeDefault,
},
"AppArmor enforced with good profile": {
pod: createPodWithAppArmor(apparmor.ProfileNamePrefix + "foo"),
pod: createPodWithAppArmor(v1.AppArmorBetaProfileNamePrefix + "foo"),
psp: appArmorDefaultPSP,
shouldPassAdmit: true,
shouldPassValidate: true,
expectedProfile: apparmor.ProfileNamePrefix + "foo",
expectedProfile: v1.AppArmorBetaProfileNamePrefix + "foo",
},
"AppArmor enforced with local profile": {
pod: createPodWithAppArmor(apparmor.ProfileNamePrefix + "bar"),
pod: createPodWithAppArmor(v1.AppArmorBetaProfileNamePrefix + "bar"),
psp: appArmorPSP,
shouldPassAdmit: false,
shouldPassValidate: false,

View File

@ -48,6 +48,22 @@ const (
// SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime.
SeccompProfileRuntimeDefault string = "runtime/default"
// AppArmorBetaContainerAnnotationKeyPrefix is the prefix to an annotation key specifying a container's apparmor profile.
AppArmorBetaContainerAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/"
// AppArmorBetaDefaultProfileAnnotatoinKey is the annotation key specifying the default AppArmor profile.
AppArmorBetaDefaultProfileAnnotationKey = "apparmor.security.beta.kubernetes.io/defaultProfileName"
// AppArmorBetaAllowedProfileAnnotationKey is the annotation key specifying the allowed AppArmor profiles.
AppArmorBetaAllowedProfilesAnnotationKey = "apparmor.security.beta.kubernetes.io/allowedProfileNames"
// AppArmorBetaProfileRuntimeDefault is the profile specifying the runtime default.
AppArmorBetaProfileRuntimeDefault = "runtime/default"
// AppArmorBetaProfileNamePrefix is the prefix for specifying profiles loaded on the node.
AppArmorBetaProfileNamePrefix = "localhost/"
// AppArmorBetaProfileNameUnconfined is the Unconfined AppArmor profile
AppArmorBetaProfileNameUnconfined = "unconfined"
// DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker.
// This is now deprecated and should be replaced by SeccompProfileRuntimeDefault.
DeprecatedSeccompProfileDockerDefault string = "docker/default"

View File

@ -17,7 +17,6 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/master/ports:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/security/podsecuritypolicy/seccomp:go_default_library",
"//pkg/security/podsecuritypolicy/util:go_default_library",
"//plugin/pkg/admission/serviceaccount:go_default_library",

View File

@ -29,7 +29,6 @@ import (
"k8s.io/apiserver/pkg/authentication/serviceaccount"
clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/security/apparmor"
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
"k8s.io/kubernetes/test/e2e/framework"
@ -173,7 +172,7 @@ func testPrivilegedPods(tester func(pod *v1.Pod)) {
ginkgo.By("Running a custom AppArmor profile pod", func() {
aa := restrictedPod("apparmor")
// Every node is expected to have the docker-default profile.
aa.Annotations[apparmor.ContainerAnnotationKeyPrefix+"pause"] = "localhost/docker-default"
aa.Annotations[v1.AppArmorBetaContainerAnnotationKeyPrefix+"pause"] = "localhost/docker-default"
tester(aa)
})
}
@ -256,8 +255,8 @@ func restrictedPod(name string) *v1.Pod {
ObjectMeta: metav1.ObjectMeta{
Name: name,
Annotations: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
apparmor.ContainerAnnotationKeyPrefix + "pause": apparmor.ProfileRuntimeDefault,
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "pause": v1.AppArmorBetaProfileRuntimeDefault,
},
},
Spec: v1.PodSpec{
@ -316,10 +315,10 @@ func restrictedPSP(name string) *policyv1beta1.PodSecurityPolicy {
ObjectMeta: metav1.ObjectMeta{
Name: name,
Annotations: map[string]string{
seccomp.AllowedProfilesAnnotationKey: v1.SeccompProfileRuntimeDefault,
seccomp.DefaultProfileAnnotationKey: v1.SeccompProfileRuntimeDefault,
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
apparmor.DefaultProfileAnnotationKey: apparmor.ProfileRuntimeDefault,
seccomp.AllowedProfilesAnnotationKey: v1.SeccompProfileRuntimeDefault,
seccomp.DefaultProfileAnnotationKey: v1.SeccompProfileRuntimeDefault,
v1.AppArmorBetaAllowedProfilesAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
v1.AppArmorBetaDefaultProfileAnnotationKey: v1.AppArmorBetaProfileRuntimeDefault,
},
},
Spec: policyv1beta1.PodSecurityPolicySpec{

View File

@ -36,14 +36,6 @@ const (
loaderLabelKey = "name"
loaderLabelValue = "e2e-apparmor-loader"
// TODO: import this from the k8s.io/api once it's moved there (ref: https://github.com/kubernetes/kubernetes/pull/89198)
// Unconfined profile
profileNameUnconfined = "unconfined"
// TODO: import this from the k8s.io/api once it's moved there (ref: https://github.com/kubernetes/kubernetes/pull/89198)
// The prefix to an annotation key specifying a container profile.
containerAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/"
)
// LoadAppArmorProfiles creates apparmor-profiles ConfigMap and apparmor-loader ReplicationController.
@ -71,7 +63,7 @@ elif [[ $(< /proc/self/attr/current) != "%[3]s" ]]; then
fi`, appArmorDeniedPath, appArmorAllowedPath, appArmorProfilePrefix+nsName)
if unconfined {
profile = profileNameUnconfined
profile = v1.AppArmorBetaProfileNameUnconfined
testCmd = `
if cat /proc/sysrq-trigger 2>&1 | grep 'Permission denied'; then
echo 'FAILURE: reading /proc/sysrq-trigger should be allowed'
@ -105,7 +97,7 @@ done`, testCmd)
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-apparmor-",
Annotations: map[string]string{
containerAnnotationKeyPrefix + "test": profile,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test": profile,
},
Labels: map[string]string{
"test": "apparmor",

View File

@ -53,11 +53,11 @@ var _ = framework.KubeDescribe("AppArmor [Feature:AppArmor][NodeFeature:AppArmor
f := framework.NewDefaultFramework("apparmor-test")
ginkgo.It("should reject an unloaded profile", func() {
status := runAppArmorTest(f, false, apparmor.ProfileNamePrefix+"non-existent-profile")
status := runAppArmorTest(f, false, v1.AppArmorBetaProfileNamePrefix+"non-existent-profile")
expectSoftRejection(status)
})
ginkgo.It("should enforce a profile blocking writes", func() {
status := runAppArmorTest(f, true, apparmor.ProfileNamePrefix+apparmorProfilePrefix+"deny-write")
status := runAppArmorTest(f, true, v1.AppArmorBetaProfileNamePrefix+apparmorProfilePrefix+"deny-write")
if len(status.ContainerStatuses) == 0 {
framework.Failf("Unexpected pod status: %s", spew.Sdump(status))
return
@ -68,7 +68,7 @@ var _ = framework.KubeDescribe("AppArmor [Feature:AppArmor][NodeFeature:AppArmor
})
ginkgo.It("should enforce a permissive profile", func() {
status := runAppArmorTest(f, true, apparmor.ProfileNamePrefix+apparmorProfilePrefix+"audit-write")
status := runAppArmorTest(f, true, v1.AppArmorBetaProfileNamePrefix+apparmorProfilePrefix+"audit-write")
if len(status.ContainerStatuses) == 0 {
framework.Failf("Unexpected pod status: %s", spew.Sdump(status))
return
@ -83,7 +83,7 @@ var _ = framework.KubeDescribe("AppArmor [Feature:AppArmor][NodeFeature:AppArmor
f := framework.NewDefaultFramework("apparmor-test")
ginkgo.It("should reject a pod with an AppArmor profile", func() {
status := runAppArmorTest(f, false, apparmor.ProfileRuntimeDefault)
status := runAppArmorTest(f, false, v1.AppArmorBetaProfileRuntimeDefault)
expectSoftRejection(status)
})
})
@ -180,7 +180,7 @@ func createPodWithAppArmor(f *framework.Framework, profile string) *v1.Pod {
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("test-apparmor-%s", strings.Replace(profile, "/", "-", -1)),
Annotations: map[string]string{
apparmor.ContainerAnnotationKeyPrefix + "test": profile,
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test": profile,
},
},
Spec: v1.PodSpec{