diff --git a/tetrate/tis0001/restrict-duplicate-peerauthentication.yaml b/tetrate/tis0001/restrict-duplicate-peerauthentication.yaml new file mode 100644 index 00000000..08a144b6 --- /dev/null +++ b/tetrate/tis0001/restrict-duplicate-peerauthentication.yaml @@ -0,0 +1,43 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: When multiple PeerAuthentication objects exist, they must have unique spec.selector.matchLabels to avoid conflicts in authentication policies. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Detect Duplicate PeerAuthentication + name: detect-duplicate-peer-authentication +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items + urlPath: /apis/security.istio.io/v1beta1/namespaces/{{request.namespace}}/peerauthentications + name: peerAuthList + match: + any: + - resources: + kinds: + - PeerAuthentication + name: detect-duplicate-peer-authentication + preconditions: + all: + - key: '{{ peerAuthList | length(@) }}' + operator: GreaterThan + value: 0 + - key: "{{ request.operation || 'BACKGROUND' }}" + operator: NotEquals + value: DELETE + validate: + deny: + conditions: + any: + - key: "{{ request.object.spec.selector.matchLabels || 'null' }}" + operator: Equals + value: "null" + - key: "{{ request.object.spec.selector.matchLabels.app }}" + operator: AnyIn + value: "{{ peerAuthList[].spec.selector.matchLabels.app }}" + message: When multiple PeerAuthentication objects exist, they must have unique spec.selector.matchLabels + validationFailureAction: Enforce diff --git a/tetrate/tis0001/restrict-duplicate-requestauthentication.yaml b/tetrate/tis0001/restrict-duplicate-requestauthentication.yaml new file mode 100644 index 00000000..a9795dd7 --- /dev/null +++ b/tetrate/tis0001/restrict-duplicate-requestauthentication.yaml @@ -0,0 +1,43 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: When multiple RequestAuthentication objects exist, they must have unique spec.selector.matchLabels to avoid conflicts in authentication policies. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Detect Duplicate RequestAuthentication + name: detect-duplicate-request-authentication +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items + urlPath: /apis/security.istio.io/v1beta1/namespaces/{{request.namespace}}/requestauthentications + name: requestAuthList + match: + any: + - resources: + kinds: + - RequestAuthentication + name: detect-duplicate-request-authentication + preconditions: + all: + - key: '{{ requestAuthList | length(@) }}' + operator: GreaterThan + value: 0 + - key: "{{ request.operation || 'BACKGROUND' }}" + operator: NotEquals + value: DELETE + validate: + deny: + conditions: + any: + - key: "{{ request.object.spec.selector.matchLabels || 'null' }}" + operator: Equals + value: "null" + - key: "{{ request.object.spec.selector.matchLabels.app }}" + operator: AnyIn + value: "{{ requestAuthList[].spec.selector.matchLabels.app }}" + message: When multiple RequestAuthentication objects exist, they must have unique spec.selector.matchLabels + validationFailureAction: Enforce diff --git a/tetrate/tis0001/restrict-duplicate-telemetry.yaml b/tetrate/tis0001/restrict-duplicate-telemetry.yaml new file mode 100644 index 00000000..007ecd6b --- /dev/null +++ b/tetrate/tis0001/restrict-duplicate-telemetry.yaml @@ -0,0 +1,43 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: When multiple Telemetry objects exist, they must have unique spec.selector.matchLabels to avoid conflicts in authentication policies. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Detect Duplicate Telemetry + name: detect-duplicate-telemetry +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items + urlPath: /apis/telemetry.istio.io/v1alpha1/namespaces/{{request.namespace}}/telemetries + name: telemetryList + match: + any: + - resources: + kinds: + - Telemetry + name: detect-duplicate-telemetry + preconditions: + all: + - key: '{{ telemetryList | length(@) }}' + operator: GreaterThan + value: 0 + - key: "{{ request.operation || 'BACKGROUND' }}" + operator: NotEquals + value: DELETE + validate: + deny: + conditions: + any: + - key: "{{ request.object.spec.selector.matchLabels || 'null' }}" + operator: Equals + value: "null" + - key: "{{ request.object.spec.selector.matchLabels.app }}" + operator: AnyIn + value: "{{ telemetryList[].spec.selector.matchLabels.app }}" + message: When multiple Telemetry objects exist, they must have unique spec.selector.matchLabels + validationFailureAction: Enforce diff --git a/tetrate/tis0003/validate-peerauthentication-app-exists.yaml b/tetrate/tis0003/validate-peerauthentication-app-exists.yaml new file mode 100644 index 00000000..0000ac30 --- /dev/null +++ b/tetrate/tis0003/validate-peerauthentication-app-exists.yaml @@ -0,0 +1,32 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: This policy ensures that the app specified in PeerAuthentication's selector exists as a Pod in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Validate PeerAuthentication App Exists + name: validate-peer-auth-app-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[?metadata.labels.app=='{{request.object.spec.selector.matchLabels.app}}'] | length(@) + urlPath: /api/v1/namespaces/{{request.namespace}}/pods + name: pods + match: + any: + - resources: + kinds: + - PeerAuthentication + name: check-app-exists + validate: + deny: + conditions: + all: + - key: '{{ pods }}' + operator: Equals + value: 0 + message: The app '{{request.object.spec.selector.matchLabels.app}}' specified in PeerAuthentication selector must exist as a Pod in the cluster + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0003/validate-requestauthentication-app-exists.yaml b/tetrate/tis0003/validate-requestauthentication-app-exists.yaml new file mode 100644 index 00000000..d271b1e7 --- /dev/null +++ b/tetrate/tis0003/validate-requestauthentication-app-exists.yaml @@ -0,0 +1,32 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: This policy ensures that the app specified in RequestAuthentication's selector exists as a Pod in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Validate RequestAuthentication App Exists + name: validate-request-auth-app-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[?metadata.labels.app=='{{request.object.spec.selector.matchLabels.app}}'] | length(@) + urlPath: /api/v1/namespaces/{{request.namespace}}/pods + name: pods + match: + any: + - resources: + kinds: + - RequestAuthentication + name: check-app-exists + validate: + deny: + conditions: + all: + - key: '{{ pods }}' + operator: Equals + value: 0 + message: The app '{{request.object.spec.selector.matchLabels.app}}' specified in RequestAuthentication selector must exist as a Pod in the cluster + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0003/validate-telemetry-app-exists.yaml b/tetrate/tis0003/validate-telemetry-app-exists.yaml new file mode 100644 index 00000000..8d0937f4 --- /dev/null +++ b/tetrate/tis0003/validate-telemetry-app-exists.yaml @@ -0,0 +1,32 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: This policy ensures that the app specified in Telemetry's selector exists as a Pod in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Validate Telemetry App Exists + name: validate-telemetry-app-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[?metadata.labels.app=='{{request.object.spec.selector.matchLabels.app}}'] | length(@) + urlPath: /api/v1/namespaces/{{request.namespace}}/pods + name: pods + match: + any: + - resources: + kinds: + - Telemetry + name: check-app-exists + validate: + deny: + conditions: + all: + - key: '{{ pods }}' + operator: Equals + value: 0 + message: The app '{{request.object.spec.selector.matchLabels.app}}' specified in Telemetry selector must exist as a Pod in the cluster + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0004/restrict-non-existent-namespace-for-authorization-policy.yaml b/tetrate/tis0004/restrict-non-existent-namespace-for-authorization-policy.yaml new file mode 100644 index 00000000..efa211a9 --- /dev/null +++ b/tetrate/tis0004/restrict-non-existent-namespace-for-authorization-policy.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Pod Security + policies.kyverno.io/description: This policy ensures that any namespace specified in the source.namespace field of an AuthorizationPolicy's rules actually exists in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: AuthorizationPolicy, Namespace + policies.kyverno.io/title: Check AuthorizationPolicy Source Namespaces Exist + name: check-authzpolicy-namespace-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[].metadata.name + urlPath: /api/v1/namespaces + name: namespaces + match: + any: + - resources: + kinds: + - AuthorizationPolicy + name: validate-source-namespaces + validate: + foreach: + - deny: + conditions: + all: + - key: '{{ element }}' + operator: AnyNotIn + value: '{{ namespaces }}' + list: request.object.spec.rules[].from[].source.namespaces[] + message: The namespace(s) specified in the source namespaces field must exist in the cluster. + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0004/restrict-non-existent-namespace-for-serviceentry.yaml b/tetrate/tis0004/restrict-non-existent-namespace-for-serviceentry.yaml new file mode 100644 index 00000000..4e3b94e9 --- /dev/null +++ b/tetrate/tis0004/restrict-non-existent-namespace-for-serviceentry.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Other + policies.kyverno.io/description: This policy ensures that any namespace specified in the spec.exportTo field of a ServiceEntry actually exists in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: ServiceEntry, Namespace + policies.kyverno.io/title: Check ServiceEntry ExportTo Namespace Exists + name: check-serviceentry-export-to-namespace-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[].metadata.name + urlPath: /api/v1/namespaces + name: namespaces + match: + any: + - resources: + kinds: + - ServiceEntry + name: validate-export-to-namespaces + validate: + foreach: + - deny: + conditions: + all: + - key: '{{ element }}' + operator: NotEquals + value: "." + - key: '{{ element }}' + operator: AnyNotIn + value: '{{ namespaces }}' + list: request.object.spec.exportTo[] + message: The namespace(s) specified in the exportTo field must exist in the cluster. + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0004/restrict-non-existent-namespace-for-virtual-service.yaml b/tetrate/tis0004/restrict-non-existent-namespace-for-virtual-service.yaml new file mode 100644 index 00000000..05365ea3 --- /dev/null +++ b/tetrate/tis0004/restrict-non-existent-namespace-for-virtual-service.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Other + policies.kyverno.io/description: This policy ensures that any namespace specified in the spec.exportTo field of a VirtualService actually exists in the cluster. + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: VirtualService, Namespace + policies.kyverno.io/title: Check VirtualService ExportTo Namespace Exists + name: check-virtualservice-export-to-namespace-exists +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[].metadata.name + urlPath: /api/v1/namespaces + name: namespaces + match: + any: + - resources: + kinds: + - VirtualService + name: validate-export-to-namespaces + validate: + foreach: + - deny: + conditions: + all: + - key: '{{ element }}' + operator: NotEquals + value: "." + - key: '{{ element }}' + operator: AnyNotIn + value: '{{ namespaces }}' + list: request.object.spec.exportTo[] + message: The namespace(s) specified in the exportTo field must exist in the cluster. + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0005/validate-root-ca-cert.yaml b/tetrate/tis0005/validate-root-ca-cert.yaml new file mode 100644 index 00000000..fa7abf2e --- /dev/null +++ b/tetrate/tis0005/validate-root-ca-cert.yaml @@ -0,0 +1,32 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: validate-root-ca-cert +spec: + background: false + rules: + - match: + any: + - resources: + kinds: + - Secret + names: + - root-ca + namespaces: + - istio-system + name: validate-root-ca-cert + validate: + deny: + conditions: + any: + - key: "{{ request.object.data.\"ca-cert.pem\" | base64_decode(@) \n | parse_x509(\"notAfter\") | date_before(\"now\") }}" + operator: Equals + value: true + - key: "{{ request.object.data.\"ca-cert.pem\" | base64_decode(@) \n | parse_x509(\"subject\") | length(@) }}" + operator: Equals + value: 0 + - key: "{{ request.object.data.\"ca-cert.pem\" | base64_decode(@) \n | parse_x509(\"san\") | length(@) }}" + operator: Equals + value: 0 + message: The root CA certificate must be valid and properly formatted + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0101/restrict-non-existent-namespace-host-serviecentry.yaml b/tetrate/tis0101/restrict-non-existent-namespace-host-serviecentry.yaml new file mode 100644 index 00000000..3b86bc9c --- /dev/null +++ b/tetrate/tis0101/restrict-non-existent-namespace-host-serviecentry.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Service Mesh + policies.kyverno.io/description: Ensures that ServiceEntry hosts reference existing namespaces + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: ServiceEntry + policies.kyverno.io/title: Validate ServiceEntry Host Namespace + name: validate-serviceentry-host-namespace +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[].metadata.name + urlPath: /api/v1/namespaces + name: namespaces + match: + any: + - resources: + kinds: + - ServiceEntry + name: validate-host-namespace + validate: + foreach: + - deny: + conditions: + all: + - key: "{{ regex_split('^[^.]+\\.([^.]+)\\.svc\\.cluster\\.local$', \nelement)[1] }}\n" + operator: AnyNotIn + value: '{{ namespaces }}' + list: request.object.spec.hosts[] + message: Host '{{ element }}' references a non-existent namespace + validationFailureAction: Audit \ No newline at end of file diff --git a/tetrate/tis0101/restrict-non-existent-namespace-host-virtual-service.yaml b/tetrate/tis0101/restrict-non-existent-namespace-host-virtual-service.yaml new file mode 100644 index 00000000..eb0bdf0a --- /dev/null +++ b/tetrate/tis0101/restrict-non-existent-namespace-host-virtual-service.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Service Mesh + policies.kyverno.io/description: Ensures that VirtualService hosts reference existing namespaces + policies.kyverno.io/severity: medium + policies.kyverno.io/subject: VirtualService + policies.kyverno.io/title: Validate VirtualService Host Namespace + name: validate-virtualservice-host-namespace +spec: + background: true + rules: + - context: + - apiCall: + jmesPath: items[].metadata.name + urlPath: /api/v1/namespaces + name: namespaces + match: + any: + - resources: + kinds: + - VirtualService + name: validate-host-namespace + validate: + foreach: + - deny: + conditions: + all: + - key: "{{ regex_split('^[^.]+\\.([^.]+)\\.svc\\.cluster\\.local$', \nelement)[1] }}\n" + operator: AnyNotIn + value: '{{ namespaces }}' + list: request.object.spec.hosts[] + message: Host '{{ element }}' references a non-existent namespace + validationFailureAction: Audit \ No newline at end of file diff --git a/tetrate/tis0102/restrict-invalid-method-authorization-policy.yaml b/tetrate/tis0102/restrict-invalid-method-authorization-policy.yaml new file mode 100644 index 00000000..ab63ea93 --- /dev/null +++ b/tetrate/tis0102/restrict-invalid-method-authorization-policy.yaml @@ -0,0 +1,48 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: | + This policy ensures that in AuthorizationPolicy resources, the spec.rules[].to[].operation.method[] field contains only valid HTTP methods or properly formatted gRPC method names in the form /package.service/method. + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Validate Authorization Policy Methods + name: validate-authorization-policy-methods +spec: + background: true + rules: + - match: + any: + - resources: + kinds: + - AuthorizationPolicy + name: validate-methods + validate: + foreach: + - elementScope: rules + foreach: + - elementScope: to + foreach: + - deny: + conditions: + all: + - key: '{{ element }}' + operator: AnyNotIn + value: + - GET + - POST + - PUT + - DELETE + - PATCH + - HEAD + - OPTIONS + - CONNECT + - TRACE + - key: '{{ regex_match(''^/[a-zA-Z0-9.]+/[a-zA-Z0-9]+$'', element) }}' + operator: Equals + value: false + list: to.operation.methods || [] + list: rules.to + list: request.object.spec.rules + message: Methods must be either valid HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, CONNECT, TRACE) or valid gRPC methods in the form /package.service/method + validationFailureAction: Enforce \ No newline at end of file diff --git a/tetrate/tis0102/restrict-invalid-method-virtualservice.yaml b/tetrate/tis0102/restrict-invalid-method-virtualservice.yaml new file mode 100644 index 00000000..eb37f062 --- /dev/null +++ b/tetrate/tis0102/restrict-invalid-method-virtualservice.yaml @@ -0,0 +1,38 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + policies.kyverno.io/category: Security + policies.kyverno.io/description: Ensures that HTTP methods specified in VirtualService resources are from an allowed set + policies.kyverno.io/severity: medium + policies.kyverno.io/title: Validate VirtualService HTTP Methods + name: validate-vs-http-methods +spec: + background: true + rules: + - match: + any: + - resources: + kinds: + - VirtualService + name: validate-http-methods + validate: + foreach: + - deny: + conditions: + all: + - key: '{{ element }}' + operator: NotIn + value: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + list: request.object.spec.http[*].match[*].method.type + message: 'The HTTP method must be one of: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH' + validationFailureAction: Enforce \ No newline at end of file