Policy: organization-sa-namespaces
Ensure that all namespaces created by organization serviceaccounts have a label appuio.io/organization
which isn’t empty.
Category |
Namespace Ownership |
Minimum Kyverno version |
v1 |
Subject |
APPUiO Organizations |
Policy types |
|
Implementation |
This policy will:
-
Check that each namespace created by a serviceaccount without cluster-admin permissions has a label appuio.io/organization which isn’t empty.
-
Check that the creating serviceaccount is part of the organization it tries to create a namespace for.
The serviceaccount’s organization membership is checked by:
-
Fetching the serviceaccount’s namespace
-
Comparing that namespace’s
appuio.io/organization
label value with the request’sappuio.io/organization
label value.
If the label appuio.io/organization
is missing or empty or the serviceaccount’s organization doesn’t match the request’s organization the request is denied.
Serviceaccounts which match an entry of component parameter bypassNamespaceRestrictions
are allowed to bypass the policy.
Policy Definition
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
annotations:
policies.kyverno.io/category: Namespace Ownership
policies.kyverno.io/description: |
This policy will:
- Check that each namespace created by a serviceaccount without cluster-admin permissions has a label appuio.io/organization which isn't empty.
- Check that the creating serviceaccount is part of the organization it tries to create a namespace for.
The serviceaccount's organization membership is checked by:
- Fetching the serviceaccount's namespace
- Comparing that namespace's `appuio.io/organization` label value with the request's `appuio.io/organization` label value.
If the label `appuio.io/organization` is missing or empty or the serviceaccount's organization doesn't match the request's organization the request is denied.
Serviceaccounts which match an entry of xref:references/parameters#_bypassnamespacerestrictions[component parameter `bypassNamespaceRestrictions`] are allowed to bypass the policy.
policies.kyverno.io/jsonnet: component/namespace-policies.jsonnet
policies.kyverno.io/minversion: v1
policies.kyverno.io/subject: APPUiO Organizations
policies.kyverno.io/title: Ensure that all namespaces created by organization
serviceaccounts have a label `appuio.io/organization` which isn't empty.
labels:
app.kubernetes.io/component: appuio-cloud
app.kubernetes.io/managed-by: commodore
app.kubernetes.io/name: appuio-cloud
name: organization-sa-namespaces
name: organization-sa-namespaces
spec:
background: false
rules:
- context:
- apiCall:
jmesPath: '@'
urlPath: /api/v1/namespaces/{{serviceAccountNamespace}}
name: saNamespace
exclude:
any:
- clusterRoles:
- cluster-admin
- cluster-image-registry-operator
- cluster-node-tuning-operator
- kyverno:generatecontroller
- kyverno:policycontroller
- multus-admission-controller-webhook
- openshift-dns-operator
- openshift-ingress-operator
- syn-admin
- syn-argocd-application-controller
- syn-argocd-server
- system:controller:generic-garbage-collector
- system:controller:operator-lifecycle-manager
- system:master
- system:openshift:controller:namespace-security-allocation-controller
- system:openshift:controller:podsecurity-admission-label-syncer-controller
- subjects:
- kind: ServiceAccount
name: argocd-application-controller
namespace: argocd
- kind: ServiceAccount
name: cluster-logging-operator
namespace: openshift-logging
- kind: ServiceAccount
name: olm-operator-serviceaccount
namespace: openshift-operator-lifecycle-manager
- kind: ServiceAccount
name: namespace-openshift-config-2c8343f13594d63-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-default-d6a0af6dd07e8a3-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-openshift-monitoring-c4273dc15ddfdf7-manager
namespace: syn-resource-locker
match:
all:
- resources:
kinds:
- Namespace
mutate:
patchStrategicMerge:
metadata:
labels:
+(appuio.io/organization): '{{saNamespace.metadata.labels."appuio.io/organization"
|| ""}}'
name: add-organization
preconditions:
all:
- key: '{{serviceAccountName}}'
operator: NotEquals
value: ''
- exclude:
any:
- clusterRoles:
- cluster-admin
- cluster-image-registry-operator
- cluster-node-tuning-operator
- kyverno:generatecontroller
- kyverno:policycontroller
- multus-admission-controller-webhook
- openshift-dns-operator
- openshift-ingress-operator
- syn-admin
- syn-argocd-application-controller
- syn-argocd-server
- system:controller:generic-garbage-collector
- system:controller:operator-lifecycle-manager
- system:master
- system:openshift:controller:namespace-security-allocation-controller
- system:openshift:controller:podsecurity-admission-label-syncer-controller
- subjects:
- kind: ServiceAccount
name: argocd-application-controller
namespace: argocd
- kind: ServiceAccount
name: cluster-logging-operator
namespace: openshift-logging
- kind: ServiceAccount
name: olm-operator-serviceaccount
namespace: openshift-operator-lifecycle-manager
- kind: ServiceAccount
name: namespace-openshift-config-2c8343f13594d63-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-default-d6a0af6dd07e8a3-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-openshift-monitoring-c4273dc15ddfdf7-manager
namespace: syn-resource-locker
match:
all:
- resources:
kinds:
- Namespace
name: has-organization
preconditions:
all:
- key: '{{serviceAccountName}}'
operator: NotEquals
value: ''
validate:
message: Namespace must have organization
pattern:
metadata:
labels:
appuio.io/organization: ?*
- context:
- apiCall:
jmesPath: '@'
urlPath: /api/v1/namespaces/{{serviceAccountNamespace}}
name: saNamespace
exclude:
any:
- clusterRoles:
- cluster-admin
- cluster-image-registry-operator
- cluster-node-tuning-operator
- kyverno:generatecontroller
- kyverno:policycontroller
- multus-admission-controller-webhook
- openshift-dns-operator
- openshift-ingress-operator
- syn-admin
- syn-argocd-application-controller
- syn-argocd-server
- system:controller:generic-garbage-collector
- system:controller:operator-lifecycle-manager
- system:master
- system:openshift:controller:namespace-security-allocation-controller
- system:openshift:controller:podsecurity-admission-label-syncer-controller
- subjects:
- kind: ServiceAccount
name: argocd-application-controller
namespace: argocd
- kind: ServiceAccount
name: cluster-logging-operator
namespace: openshift-logging
- kind: ServiceAccount
name: olm-operator-serviceaccount
namespace: openshift-operator-lifecycle-manager
- kind: ServiceAccount
name: namespace-openshift-config-2c8343f13594d63-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-default-d6a0af6dd07e8a3-manager
namespace: syn-resource-locker
- kind: ServiceAccount
name: namespace-openshift-monitoring-c4273dc15ddfdf7-manager
namespace: syn-resource-locker
match:
all:
- resources:
kinds:
- Namespace
name: is-in-organization
preconditions:
all:
- key: '{{serviceAccountName}}'
operator: NotEquals
value: ''
- key: '{{request.object.metadata.labels."appuio.io/organization" || ""}}'
operator: NotEquals
value: ''
validate:
deny:
conditions:
- key: '{{request.object.metadata.labels."appuio.io/organization"}}'
operator: NotEquals
value: '{{saNamespace.metadata.labels."appuio.io/organization"}}'
message: Creating namespace for {{request.object.metadata.labels."appuio.io/organization"}}
but {{serviceAccountName}} is not in organization
validationFailureAction: enforce