diff --git a/components/policies/production/base/cost-management/kustomization.yaml b/components/policies/production/base/cost-management/kustomization.yaml new file mode 100644 index 00000000000..48258cf8b37 --- /dev/null +++ b/components/policies/production/base/cost-management/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- propagate-cost-management-labels/ +- validate-cost-management-labels/ diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml new file mode 100644 index 00000000000..b8dbecb47fd --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: propagate-cost-management-labels +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml new file mode 100644 index 00000000000..be6c906d132 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,195 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: label-propagation-valid-cost-center +spec: + concurrent: false + description: | + tests that the labels are correctly set on pods in tenant namespace + that have the `cost-center` label + steps: + - name: Create namespaces for testing + try: + - create: + file: ./resources/namespace-cost-center.yaml + template: true + bindings: + - name: namespace + value: tenant + - name: cost_center + value: "670" + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../propagate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: propagate-cost-management-labels + - name: create pods in tenant + try: + - create: + file: ./resources/pod.yaml + bindings: + - name: namespace + value: tenant + template: true + - name: assert pods in the tenant are labeled + try: + - assert: + file: ./resources/expected-pod-matching.yaml + template: true + bindings: + - name: namespace + value: tenant + - name: cost_center + value: "670" +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: label-not-applied-random-ns +spec: + concurrent: false + description: | + tests that the label is not applied to pods in a non-tenant namespace + steps: + - name: Create namespaces for testing + try: + - create: + file: ./resources/namespace-nonmatching.yaml + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../propagate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: propagate-cost-management-labels + - name: create pods in random-ns + try: + - create: + file: ./resources/pod.yaml + template: true + bindings: + - name: namespace + value: random-ns + - name: assert pods in random-ns are not labeled + try: + - assert: + file: ./resources/pod.yaml + template: true + bindings: + - name: namespace + value: random-ns +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: rule-not-applied-to-rhtap-releng-tenant +spec: + concurrent: false + description: | + Tests that the Kyverno policy does not apply to pods in managed tenant namespaces. + steps: + - name: Create a managed namespace + try: + - create: + file: ./resources/namespace-no-cost-center.yaml + template: true + bindings: + - name: namespace + value: rhtap-releng-tenant + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../propagate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: propagate-cost-management-labels + - name: Create a pod in the namespace + try: + - create: + file: ./resources/pod.yaml + template: true + bindings: + - name: namespace + value: rhtap-releng-tenant + - name: Assert pod in namespace is not labeled + try: + - assert: + resource: + apiVersion: v1 + kind: Pod + metadata: + name: demo-pod + namespace: rhtap-releng-tenant + labels: {} +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: create-pod-in-tenant-namespace-without-cost-center +spec: + concurrent: false + description: | + Tests that it is possible to create a pod in an existing tenant namespace + that does not have the `cost-center` label. + steps: + - name: Create a tenant namespace without cost-center label + try: + - create: + file: ./resources/namespace-no-cost-center.yaml + template: true + bindings: + - name: namespace + value: tenant-no-cost-center + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../propagate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: propagate-cost-management-labels + - name: Create a pod in the tenant namespace without cost-center label + try: + - create: + file: ./resources/pod.yaml + template: true + bindings: + - name: namespace + value: tenant-no-cost-center + - name: Assert pod in tenant namespace is created successfully + try: + - assert: + file: ./resources/pod.yaml + template: true + bindings: + - name: namespace + value: tenant-no-cost-center diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/expected-pod-matching.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/expected-pod-matching.yaml new file mode 100644 index 00000000000..e605bd0a3fc --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/expected-pod-matching.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: demo-pod + namespace: ($namespace) + labels: + cost-center: ($cost_center) + cost_management_optimizations: "true" diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml new file mode 100644 index 00000000000..40372397e31 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ($namespace) + labels: + konflux-ci.dev/type: tenant + cost-center: ($cost_center) + cost_management_optimizations: "true" diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml new file mode 100644 index 00000000000..a47d06ee588 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ($namespace) + labels: + konflux-ci.dev/type: tenant diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml new file mode 100644 index 00000000000..f083e396e21 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: random-ns diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/pod.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/pod.yaml new file mode 100644 index 00000000000..ae9ef8608c7 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/.chainsaw-test/resources/pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: demo-pod + namespace: ($namespace) + labels: + app: test-app +spec: + containers: + - name: test-container + image: nginx diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/kustomization.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/kustomization.yaml new file mode 100644 index 00000000000..2c706cfc4bf --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- propagate-cost-management-labels.yaml +- kyverno-rbac.yaml diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/kyverno-rbac.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/kyverno-rbac.yaml new file mode 100644 index 00000000000..33e12b1dd22 --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/kyverno-rbac.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kyverno-admission-propagate-cost-management-labels + labels: + rbac.kyverno.io/aggregate-to-admission-controller: "true" +rules: +- apiGroups: + - "" + resources: + - pods + - namespaces + verbs: + - list + - get diff --git a/components/policies/production/base/cost-management/propagate-cost-management-labels/propagate-cost-management-labels.yaml b/components/policies/production/base/cost-management/propagate-cost-management-labels/propagate-cost-management-labels.yaml new file mode 100644 index 00000000000..4c39496abdc --- /dev/null +++ b/components/policies/production/base/cost-management/propagate-cost-management-labels/propagate-cost-management-labels.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: propagate-cost-management-labels + annotations: + policies.kyverno.io/title: Propagate Cost-Center from Namespace + policies.kyverno.io/category: Cost Management + policies.kyverno.io/severity: low + policies.kyverno.io/subject: Pod + policies.kyverno.io/description: >- + Propagates the `cost-center` label from non-managed tenant namespaces to pods, + and sets the `cost_management_optimizations` label to `true` on those pods. +spec: + webhookConfiguration: + failurePolicy: Ignore + rules: + - name: propagate-existing-cost-center-from-namespace + skipBackgroundRequests: true + match: + any: + - resources: + kinds: + - Pod + namespaceSelector: + matchLabels: + konflux-ci.dev/type: tenant + matchExpressions: + - key: kubernetes.io/metadata.name + operator: NotIn + values: + # managed tenant namespaces + - rhtap-releng-tenant + - rh-managed-bifrost-tenant + - rh-managed-cnv-fbc-tenant + - rh-managed-mng-s-2-tenant + - rh-managed-red-hat-acm-tenant + - rh-managed-rhtap-ser-tenant + - rhel-on-gitlab-tenant + context: + - name: costcenterLabel + apiCall: + urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}" + method: GET + jmesPath: "metadata.labels.\"cost-center\" || '' " + preconditions: + all: + - key: "{{ costcenterLabel }}" + operator: NotEquals + value: "" + mutate: + patchStrategicMerge: + metadata: + labels: + cost-center: "{{ costcenterLabel }}" + cost_management_optimizations: "true" diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml new file mode 100644 index 00000000000..8a6aee1f19c --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-assert-clusterpolicy.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: validate-cost-management-labels +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml new file mode 100644 index 00000000000..605aff7eefc --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/chainsaw-test.yaml @@ -0,0 +1,186 @@ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: allow-namespace-with-cost-center +spec: + concurrent: false + description: | + Tests that a namespace labeled as `konflux-ci.dev/type: tenant` + is allowed only if it has the `cost-center` label. + steps: + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../validate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: validate-cost-management-labels + - name: Create a tenant namespace with cost-center label + try: + - create: + file: ./resources/namespace-cost-center.yaml + template: true + bindings: + - name: namespace + value: tenant + - name: cost_center + value: "670" + expect: + - match: + kind: Namespace + check: + ($error == null): true +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: allow-namespace-without-tenant-label +spec: + concurrent: false + description: | + Tests that a namespace without the `konflux-ci.dev/type: tenant` label + is allowed regardless of the `cost-center` label. + steps: + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../validate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: validate-cost-management-labels + - name: Create a namespace without tenant label + try: + - create: + file: ./resources/namespace-nonmatching.yaml + expect: + - match: + kind: Namespace + check: + ($error == null): true +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: deny-namespace-with-empty-cost-center +spec: + concurrent: false + description: | + Tests that a namespace labeled as `konflux-ci.dev/type: tenant` + is denied if the `cost-center` label is empty. + steps: + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../validate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: validate-cost-management-labels + - name: Attempt to create a tenant namespace with empty cost-center label + try: + - create: + file: ./resources/namespace-empty-cost-center.yaml + expect: + - match: + kind: Namespace + check: + ($error != null): true +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: deny-namespace-without-cost-center +spec: + concurrent: false + description: | + Tests that a namespace labeled as `konflux-ci.dev/type: tenant` + is denied if it does not have the `cost-center` label. + steps: + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../validate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: validate-cost-management-labels + - name: Attempt to create a tenant namespace without cost-center label + try: + - create: + file: ./resources/namespace-no-cost-center.yaml + template: true + bindings: + - name: namespace + value: tenant-no-cost-center + expect: + - match: + kind: Namespace + check: + ($error != null): true +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: deny-namespace-with-invalid-cost-center +spec: + concurrent: false + description: | + Tests that a namespace labeled as `konflux-ci.dev/type: tenant` + is denied if the `cost-center` label is invalid. + steps: + - name: Apply RBAC + try: + - apply: + file: ../kyverno-rbac.yaml + - name: Apply Kyverno Cluster Policy and assert it exists + try: + - apply: + file: ../validate-cost-management-labels.yaml + - assert: + file: chainsaw-assert-clusterpolicy.yaml + template: true + bindings: + - name: cluster_policy_name + value: validate-cost-management-labels + - name: Attempt to create a tenant namespace with invalid cost-center label + try: + - create: + file: ./resources/namespace-cost-center.yaml + template: true + bindings: + - name: namespace + value: tenant + - name: cost_center + value: "invalid-should-be-all-numbers" + expect: + - match: + kind: Namespace + check: + ($error != null): true diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml new file mode 100644 index 00000000000..40372397e31 --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-cost-center.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ($namespace) + labels: + konflux-ci.dev/type: tenant + cost-center: ($cost_center) + cost_management_optimizations: "true" diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-empty-cost-center.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-empty-cost-center.yaml new file mode 100644 index 00000000000..bf104e9dcff --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-empty-cost-center.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: tenant-empty-cost-center + labels: + konflux-ci.dev/type: tenant + cost-center: "" + cost_management_optimizations: "true" diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml new file mode 100644 index 00000000000..a47d06ee588 --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-no-cost-center.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ($namespace) + labels: + konflux-ci.dev/type: tenant diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml new file mode 100644 index 00000000000..f083e396e21 --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/.chainsaw-test/resources/namespace-nonmatching.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: random-ns diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/kustomization.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/kustomization.yaml new file mode 100644 index 00000000000..67263838b4f --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- validate-cost-management-labels.yaml +- kyverno-rbac.yaml diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/kyverno-rbac.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/kyverno-rbac.yaml new file mode 100644 index 00000000000..d208ced98f2 --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/kyverno-rbac.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kyverno-admission-validate-cost-management-labels + labels: + rbac.kyverno.io/aggregate-to-admission-controller: "true" +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - get diff --git a/components/policies/production/base/cost-management/validate-cost-management-labels/validate-cost-management-labels.yaml b/components/policies/production/base/cost-management/validate-cost-management-labels/validate-cost-management-labels.yaml new file mode 100644 index 00000000000..087cd0e78b7 --- /dev/null +++ b/components/policies/production/base/cost-management/validate-cost-management-labels/validate-cost-management-labels.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: validate-cost-management-labels + annotations: + policies.kyverno.io/title: Validate Cost-Management label + policies.kyverno.io/category: Cost Management + policies.kyverno.io/severity: low + policies.kyverno.io/subject: Namespace + policies.kyverno.io/description: >- + This policy ensures that: + (1) New tenant namespaces have the `cost-management` label. + (2) The `cost-management` label value contains only numeric characters. +spec: + validationFailureAction: Enforce + rules: + - name: validate-cost-center-label + skipBackgroundRequests: true + match: + any: + - resources: + kinds: + - Namespace + selector: + matchLabels: + konflux-ci.dev/type: tenant + validate: + allowExistingViolations: true + message: "Tenant namespaces must have the 'cost-center' label." + pattern: + metadata: + labels: + cost-center: "?*" + - name: validate-cost-center-label-value + skipBackgroundRequests: true + match: + any: + - resources: + kinds: + - Namespace + operations: + - CREATE + - UPDATE + selector: + matchLabels: + konflux-ci.dev/type: tenant + cost-center: "?*" + validate: + allowExistingViolations: true + message: "Tenant namespaces 'cost-center' label can only contain numbers." + cel: + expressions: + - expression: "object.metadata.labels['cost-center'].matches('^[0-9]+$')" diff --git a/components/policies/production/stone-prod-p01/kustomization.yaml b/components/policies/production/stone-prod-p01/kustomization.yaml index 5088ede4222..b40c2749797 100644 --- a/components/policies/production/stone-prod-p01/kustomization.yaml +++ b/components/policies/production/stone-prod-p01/kustomization.yaml @@ -2,5 +2,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../base +- ../base/cost-management - ../policies/kueue/ - ../policies/kubearchive/