config/helm/templates/validatingadmissionpolicies.yaml (112 lines of code) (raw):
# This policy validates the configuration of the tokens that are created by the msi-acrpull controller.
# It requires the parameters controllerServiceAccountName, controllerNamespace, token expiration, and token audiences
# to be set in the ConfigMap admission-policies-controller-config.
# The user must configure:
# the token audiences
# the controllerServiceAccountName and controllerNamespace parameters
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "controller-token-request-policy"
labels:
app.kubernetes.io/name: acrpull
app.kubernetes.io/managed-by: Helm
spec:
failurePolicy: Fail
paramKind:
apiVersion: v1
kind: ConfigMap
matchConditions:
- name: 'userIsController'
expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName"
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["serviceaccounts/token"]
variables:
- name: requestHasOnlyOneAudience
expression: "object.spec.audiences.size() == 1"
- name: hasCorrectAudience
expression: "object.spec.audiences.exists(w, w == params.data.tokenAudience)"
validations:
- expression: "variables.hasCorrectAudience == true && variables.requestHasOnlyOneAudience == true" # if the expression evaluates to false, the validation check is enforced according to the failurePolicy
messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' ' + string(request.name) + ' token in the ' + string(request.namespace) + ' namespace. Check the configuration.'"
reason: "Forbidden"
---
# This policy is used to restrict the types of secrets that the controller can create or update. We only allow the controller
# to create dockerconfigjson secret types, as allowing other types would allow privilege escalations and unwanted behavior.
# (For example, service account token secret types get auto-populated with tokens.)
# We furthermore restrict the controller to creating and updating secrets with the label we use for limiting our informers.
# It requires the parameter controllerName, controllerNamespace and the list of secret types to allow to be set in the
# ConfigMap admission-policies-controller-config.
# The user must configure:
# the controllerServiceAccountName and controllerNamespace parameters
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "controller-secret-mutation-policy"
labels:
app.kubernetes.io/name: acrpull
app.kubernetes.io/managed-by: Helm
spec:
failurePolicy: Fail
paramKind:
apiVersion: v1
kind: ConfigMap
matchConditions:
- name: 'userIsController'
expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName"
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE","UPDATE"]
resources: ["secrets"]
variables:
- name: hasOwner
expression: "has(object.metadata.ownerReferences) && (size(object.metadata.ownerReferences) == 1 && object.metadata.ownerReferences.all(o, o.kind == 'AcrPullBinding' && (o.apiVersion.startsWith('msi-acrpull.microsoft.com/') || o.apiVersion.startsWith('acrpull.microsoft.com/'))))"
- name: matchesPreviousOwner
expression: "has(oldObject.metadata) ? oldObject.metadata.ownerReferences == object.metadata.ownerReferences : true"
- name: hasSecretType
expression: "object.type == 'kubernetes.io/dockerconfigjson'"
- name: matchesPreviousSecretType
expression: "has(oldObject.metadata) ? oldObject.type == object.type : true"
- name: hasLabel
expression: "object.metadata.name.matches('-msi-acrpull-secret$') ? true : (has(object.metadata.labels) && ('acr.microsoft.com/binding' in object.metadata.?labels.orValue({})))"
- name: matchesPreviousLabel
expression: "object.metadata.name.matches('-msi-acrpull-secret$') ? true : (has(oldObject.metadata) ? oldObject.metadata.labels == object.metadata.labels : true)"
validations:
- expression: "variables.hasOwner == true && variables.matchesPreviousOwner == true && variables.hasSecretType == true && variables.matchesPreviousSecretType == true && variables.hasLabel == true && variables.matchesPreviousLabel == true"
messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' secret with ' + string(object.type) + ' type ' + 'in the ' + string(request.namespace) + ' namespace. The controller can only create or update secrets that it owns, with the correct type and having the correct label.' + string(variables.hasOwner == true) + string(variables.matchesPreviousOwner == true) + string(variables.hasSecretType == true) + string(variables.matchesPreviousSecretType == true) + string(variables.hasLabel == true) + string(variables.matchesPreviousLabel == true )"
reason: "Forbidden"
---
# This policy will deny updates to serviceAccounts that do something other than changing the list of managed pull secrets.
# It requires the parameter controllerServiceAccountName and controllerNamespace to be set in the
# ConfigMap admission-policies-controller-config.
# The user must configure:
# the controllerServiceAccountName and controllerNamespace parameters
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "controller-service-account-mutation-policy"
labels:
app.kubernetes.io/name: acrpull
app.kubernetes.io/managed-by: Helm
spec:
failurePolicy: Fail
paramKind:
apiVersion: v1
kind: ConfigMap
matchConditions:
- name: 'userIsController'
expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName"
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["UPDATE"]
resources: ["serviceaccounts"]
variables:
- name: secretsUnchanged
expression: "oldObject.?secrets == object.?secrets"
- name: automountUnchanged
expression: "oldObject.?automountServiceAccountToken == object.?automountServiceAccountToken"
- name: previousPullSecretNames
expression: "oldObject.?imagePullSecrets.orValue([]).map(s, s.name)"
- name: pullSecretNames
expression: "object.?imagePullSecrets.orValue([]).map(s, s.name)"
- name: addedPullSecrets
expression: "variables.pullSecretNames.filter(s, !(s in variables.previousPullSecretNames))"
- name: removedPullSecrets
expression: "variables.previousPullSecretNames.filter(s, !(s in variables.pullSecretNames))"
- name: onlyCorrectPullSecretsAdded
expression: "variables.addedPullSecrets.all(s, s.matches('^acr-pull-') || s.matches('-msi-acrpull-secret$'))"
- name: onlyCorrectPullSecretsRemoved
expression: "variables.removedPullSecrets.all(s, s.matches('^acr-pull-') || s.matches('-msi-acrpull-secret$'))"
validations:
- expression: "variables.secretsUnchanged == true && variables.automountUnchanged == true && variables.onlyCorrectPullSecretsAdded == true && variables.onlyCorrectPullSecretsRemoved == true"
messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' service account ' + string(request.name) + ' in the ' + string(request.namespace) + ' namespace. The controller may only update service accounts to add or remove pull secrets that the controller manages.' + string(variables.automountUnchanged == true) + string(variables.automountUnchanged == true) + string(variables.onlyCorrectPullSecretsAdded == true) + string(variables.onlyCorrectPullSecretsRemoved == true)"
reason: "Forbidden"