podsecurity: annotations on responses allowed by exemption

This commit is contained in:
Stanislav Laznicka 2021-10-25 16:29:07 +02:00
parent 657412713b
commit 4a79488ac2
No known key found for this signature in database
GPG Key ID: C98C414936B1A7F3
3 changed files with 59 additions and 22 deletions

View File

@ -286,7 +286,7 @@ func (a *Admission) ValidateNamespace(ctx context.Context, attrs api.Attributes)
return sharedAllowedResponse()
}
if a.exemptNamespace(attrs.GetNamespace()) {
return sharedAllowedResponse()
return sharedAllowedByNamespaceExemptionResponse()
}
response := allowedResponse()
response.Warnings = a.EvaluatePodsInNamespace(ctx, namespace.Name, newPolicy.Enforce)
@ -319,8 +319,12 @@ func (a *Admission) ValidatePod(ctx context.Context, attrs api.Attributes) *admi
return sharedAllowedResponse()
}
// short-circuit on exempt namespaces and users
if a.exemptNamespace(attrs.GetNamespace()) || a.exemptUser(attrs.GetUserName()) {
return sharedAllowedResponse()
if a.exemptNamespace(attrs.GetNamespace()) {
return sharedAllowedByNamespaceExemptionResponse()
}
if a.exemptUser(attrs.GetUserName()) {
return sharedAllowedByUserExemptionResponse()
}
// short-circuit on privileged enforce+audit+warn namespaces
@ -371,8 +375,12 @@ func (a *Admission) ValidatePodController(ctx context.Context, attrs api.Attribu
return sharedAllowedResponse()
}
// short-circuit on exempt namespaces and users
if a.exemptNamespace(attrs.GetNamespace()) || a.exemptUser(attrs.GetUserName()) {
return sharedAllowedResponse()
if a.exemptNamespace(attrs.GetNamespace()) {
return sharedAllowedByNamespaceExemptionResponse()
}
if a.exemptUser(attrs.GetUserName()) {
return sharedAllowedByUserExemptionResponse()
}
// short-circuit on privileged audit+warn namespaces
@ -409,7 +417,7 @@ func (a *Admission) ValidatePodController(ctx context.Context, attrs api.Attribu
func (a *Admission) EvaluatePod(ctx context.Context, nsPolicy api.Policy, nsPolicyErr error, podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec, attrs api.Attributes, enforce bool) *admissionv1.AdmissionResponse {
// short-circuit on exempt runtimeclass
if a.exemptRuntimeClass(podSpec.RuntimeClassName) {
return sharedAllowedResponse()
return sharedAllowedByRuntimeClassExemptionResponse()
}
auditAnnotations := map[string]string{}
@ -565,17 +573,41 @@ func (a *Admission) PolicyToEvaluate(labels map[string]string) (api.Policy, fiel
return api.PolicyToEvaluate(labels, a.defaultPolicy)
}
var _sharedAllowedResponse = allowedResponse()
var (
_sharedAllowedResponse = allowedResponse()
_sharedAllowedByUserExemptionResponse = allowedByExemptResponse("user")
_sharedAllowedByNamespaceExemptionResponse = allowedByExemptResponse("namespace")
_sharedAllowedByRuntimeClassExemptionResponse = allowedByExemptResponse("runtimeClass")
)
func sharedAllowedResponse() *admissionv1.AdmissionResponse {
return _sharedAllowedResponse
}
func sharedAllowedByUserExemptionResponse() *admissionv1.AdmissionResponse {
return _sharedAllowedByUserExemptionResponse
}
func sharedAllowedByNamespaceExemptionResponse() *admissionv1.AdmissionResponse {
return _sharedAllowedByNamespaceExemptionResponse
}
func sharedAllowedByRuntimeClassExemptionResponse() *admissionv1.AdmissionResponse {
return _sharedAllowedByRuntimeClassExemptionResponse
}
// allowedResponse is the response used when the admission decision is allow.
func allowedResponse() *admissionv1.AdmissionResponse {
return &admissionv1.AdmissionResponse{Allowed: true}
}
func allowedByExemptResponse(exemptionReason string) *admissionv1.AdmissionResponse {
return &admissionv1.AdmissionResponse{
Allowed: true,
AuditAnnotations: map[string]string{api.ExemptionReasonAnnotationKey: exemptionReason},
}
}
func failureResponse(msg string, reason metav1.StatusReason, code int32) *admissionv1.AdmissionResponse {
return &admissionv1.AdmissionResponse{
Allowed: false,

View File

@ -609,25 +609,28 @@ func TestValidatePodController(t *testing.T) {
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
},
{
desc: "namespace in exemptNamespaces will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptNamespaces: []string{testNamespace},
desc: "namespace in exemptNamespaces will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptNamespaces: []string{testNamespace},
expectAuditAnnotations: map[string]string{"exempt": "namespace"},
},
{
desc: "runtimeClass in exemptRuntimeClasses will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptRuntimeClasses: []string{"containerd"},
desc: "runtimeClass in exemptRuntimeClasses will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptRuntimeClasses: []string{"containerd"},
expectAuditAnnotations: map[string]string{"exempt": "runtimeClass"},
},
{
desc: "user in exemptUsers will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptUsers: []string{"testuser"},
desc: "user in exemptUsers will be exempted",
newObject: &badDeploy,
gvk: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
exemptUsers: []string{"testuser"},
expectAuditAnnotations: map[string]string{"exempt": "user"},
},
{
desc: "podMetadata == nil && podSpec == nil will skip verification",

View File

@ -43,4 +43,6 @@ const (
AuditVersionLabel = labelPrefix + "audit-version"
WarnLevelLabel = labelPrefix + "warn"
WarnVersionLabel = labelPrefix + "warn-version"
ExemptionReasonAnnotationKey = "exempt"
)