Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modification of some policies to read data from ConfigMap #44

Open
chipzoller opened this issue Feb 28, 2023 · 5 comments
Open

Modification of some policies to read data from ConfigMap #44

chipzoller opened this issue Feb 28, 2023 · 5 comments

Comments

@chipzoller
Copy link
Contributor

Some policies we can modify to read data from a ConfigMap rather than defined statically in the policy. Cases like checking for annotations, labels, base images, and others could be modified.

@chipzoller
Copy link
Contributor Author

Some working examples:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: allowed-base-images
  annotations:
    policies.kyverno.io/title: Allowed Base Images
    policies.kyverno.io/category: Other
    policies.kyverno.io/severity: medium
    kyverno.io/kyverno-version: 1.7.0
    policies.kyverno.io/minversion: 1.7.0
    kyverno.io/kubernetes-version: "1.23"
    policies.kyverno.io/subject: Pod
    policies.kyverno.io/description: >-
      Building images which specify a base as their origin is a good start
      to improving supply chain security, but over time organizations
      may want to build an allow list of specific base images which
      are allowed to be used when constructing containers. This policy ensures
      that a container's base, found in an OCI annotation, is in a cluster-wide
      allow list.      
spec:
  validationFailureAction: audit
  rules:
  - name: allowed-base-images
    match:
      any:
      - resources:
          kinds:
          - Pod
    preconditions:
      all:
      - key: "{{request.operation || 'BACKGROUND'}}"
        operator: NotEquals
        value: DELETE
    context:
    - name: baseimages
      configMap:
        name: baseimages
        namespace: platform
    validate:
      message: >-
        This container image's base is not in the approved list or is not specified. Only pre-approved
        base images may be used. Please contact the platform team for assistance.        
      foreach:
      - list: "request.object.spec.containers"
        context:
        - name: imageData
          imageRegistry: 
            reference: "{{ element.image }}"
        - name: basename
          variable:
            jmesPath: imageData.manifest.annotations."org.opencontainers.image.base.name"
            default: ''
        deny:
          conditions:
            all:
              - key: "{{ basename }}"
                operator: AnyNotIn
                value: "{{ baseimages.data.allowedbaseimages }}"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: advanced-restrict-image-registries
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: validate-corp-registries
      match:
        any:
        - resources:
            kinds:
            - Pod
      context:
        - name: registries
          configMap:
            name: allowed-image-registries
            namespace: platform
      preconditions:
        any:
        - key: "{{request.operation || 'BACKGROUND'}}"
          operator: AnyIn
          value:
          - CREATE
          - UPDATE
      validate:
        message: This Pod names an image that is not from an approved registry.
        foreach:
        - list: "request.object.spec.[initContainers, ephemeralContainers, containers][]"
          deny:
            conditions:
              all:
                - key: "{{element.image}}"
                  operator: AnyNotIn
                  value: "{{parse_yaml(registries.data.registries)}}"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: allowed-ingress-hosts
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: validate-hosts
      match:
        any:
        - resources:
            kinds:
            - Ingress
      context:
        - name: hosts
          configMap:
            name: allowed-ingress-hosts
            namespace: platform
      preconditions:
        any:
        - key: "{{request.operation || 'BACKGROUND'}}"
          operator: AnyIn
          value:
          - CREATE
          - UPDATE
      validate:
        message: Ingress contains a host that isn't in the allowed list.
        deny:
          conditions:
            all:
              - key: "{{ request.object.spec.rules[].host[] }}"
                operator: AnyNotIn
                value: "{{ parse_yaml(hosts.data.hostnames) }}"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: required-annotations
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: all-annotations
      match:
        any:
        - resources:
            kinds:
            - Pod
            - Secret
      context:
        - name: annotations
          configMap:
            name: required-annotations
            namespace: platform
      preconditions:
        any:
        - key: "{{request.operation || 'BACKGROUND'}}"
          operator: AnyIn
          value:
          - CREATE
          - UPDATE
      validate:
        message: Does not contain all of the required annotations.
        deny:
          conditions:
            all:
              - key: "{{ parse_yaml(annotations.data.required) }}"
                operator: AnyNotIn
                value: "{{ keys(request.object.metadata.annotations) || `[]` }}"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: required-labels
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: all-labels
      match:
        any:
        - resources:
            kinds:
            - Pod
            - Secret
      context:
        - name: labels
          configMap:
            name: required-labels
            namespace: platform
      preconditions:
        any:
        - key: "{{request.operation || 'BACKGROUND'}}"
          operator: AnyIn
          value:
          - CREATE
          - UPDATE
      validate:
        message: Does not contain all of the required labels.
        deny:
          conditions:
            all:
              - key: "{{ parse_yaml(labels.data.required) }}"
                operator: AnyNotIn
                value: "{{ keys(request.object.metadata.labels) || `[]` }}"

@patelrit
Copy link
Contributor

Can we add these to the appropriate policy set? We will then add logic to create these configmaps when the policy set is deployed by the operator.

@chipzoller
Copy link
Contributor Author

These need a little more thought and QA. I have done the basics but there may be some adjustments needed here. For example, should we use a central ConfigMap with individual keys? Separate ConfigMaps? Etc.

@patelrit
Copy link
Contributor

patelrit commented Feb 28, 2023

For now, lets use separate config maps. We may want to add annotations indicating that the policy uses an external data source (e.g. external-data-source: ConfigMap. external-data-source-name: required-labels

This could make it flexible when we deploy this via automation/operator

@chipzoller
Copy link
Contributor Author

Maybe it's best to add them in a separate, top-level folder but not replace anything existing until we refine them a bit more? They need more QA for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants