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..685f90e2173 --- /dev/null +++ b/components/policies/production/base/cost-management/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../../../development/cost-management/ +## TODO(@filariow): move it to development when KubeSaw is removed +- validate-cost-management-labels/ 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/base/kustomization.yaml b/components/policies/production/base/kustomization.yaml index 4f037dc196e..5da07522ebb 100644 --- a/components/policies/production/base/kustomization.yaml +++ b/components/policies/production/base/kustomization.yaml @@ -1,6 +1,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: +- cost-management - integration - konflux-rbac - namespace-lister