'Restrict Ingress/Egress CIDR Ranges – OPA Gatekeeper NetworkPolicy

I am trying to deploy some Restrict Ingress/Egress CIDR Ranges through OPA gatekeeper network policy.

So first I have to create constrainttemplate which will apply any kind of ingress/egress access to any IP or IP CIDR ranges except the ones which are allowed with below yaml file:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyegress
spec:
  crd:
    spec:
      names:
        kind: K8sDenyEgress
      validation:
          openAPIV3Schema:
                  properties:
                        cidr:
                                type: array
                                items:
                                        type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenyegress 
        violation [{"msg": msg}] {
            input.review.object.kind == "NetworkPolicy"
            cidr_or_ip :=  { ip | ip := input.review.object.spec.egress[_].to[_].ipBlock.cidr}
            cidr := { ip | ip := input.parameters.cidr[_]}
            value := net.cidr_contains(cidr, cidr_or_ip)
            not(value)
            msg := "The specified IP is not allowed."
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyEgress
metadata:
  name: deny-egress
spec:
  match:
    kinds:
      - apiGroups: ["networking.k8s.io"]
        kinds: ["NetworkPolicy"]
  parameters:
          cidr:
              - "192.168.0.1/24"

Once after the deployment getting below error:

Target:  admission.k8s.gatekeeper.sh
Status:
  By Pod:
    Errors:
      Code:               ingest_error
      Message:            Could not ingest Rego: 1 error occurred: __modset_templates["admission.k8s.gatekeeper.sh"]["K8sDenyEgress"]_idx_0:7: rego_type_error: net.cidr_contains: invalid argument(s)
                          have: (set[any], set[any], ???)
                          want: (string, string, boolean)
    Id:                   gatekeeper-audit-54c9759898-xxdmd
    Observed Generation:  1
    Operations:
      audit
      status
    Template UID:  f29e2dd0-5918-48a7-b943-23f36b91690f
    Errors:
      Code:               ingest_error
      Message:            Could not ingest Rego: 1 error occurred: __modset_templates["admission.k8s.gatekeeper.sh"]["K8sDenyEgress"]_idx_0:7: rego_type_error: net.cidr_contains: invalid argument(s)
                          have: (set[any], set[any], ???)
                          want: (string, string, boolean)
    Id:                   gatekeeper-controller-manager-6bcc7f8fb5-fjbfq
    Observed Generation:  1
    Operations:
      webhook
    Template UID:  f29e2dd0-5918-48a7-b943-23f36b91690f
    Errors:
      Code:               ingest_error
      Message:            Could not ingest Rego: 1 error occurred: __modset_templates["admission.k8s.gatekeeper.sh"]["K8sDenyEgress"]_idx_0:7: rego_type_error: net.cidr_contains: invalid argument(s)
                          have: (set[any], set[any], ???)
                          want: (string, string, boolean)
    Id:                   gatekeeper-controller-manager-6bcc7f8fb5-gwhrl
    Observed Generation:  1
    Operations:
webhook
    Template UID:  f29e2dd0-5918-48a7-b943-23f36b91690f
    Errors:
      Code:               ingest_error
      Message:            Could not ingest Rego: 1 error occurred: __modset_templates["admission.k8s.gatekeeper.sh"]["K8sDenyEgress"]_idx_0:7: rego_type_error: net.cidr_contains: invalid argument(s)
                          have: (set[any], set[any], ???)
                          want: (string, string, boolean)
    Id:                   gatekeeper-controller-manager-6bcc7f8fb5-sc67f
    Observed Generation:  1
    Operations:
      webhook
    Template UID:  f29e2dd0-5918-48a7-b943-23f36b91690f
  Created:         true
Events:            <none>

Could you please help out with resolving this error?



Solution 1:[1]

The function cidr_contains does not accept sets as parameters, see documentation. I used the function cidr_contains_matches instead as follows:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyegress
spec:
  crd:
    spec:
      names:
        kind: K8sDenyEgress
      validation:
        openAPIV3Schema:
          properties:
            cidr:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenyegress 

        violation [{"msg": msg}] {
            input.review.object.kind == "NetworkPolicy"
            egress_cidrs :=  { cidr | cidr := input.review.object.spec.egress[_].to[_].ipBlock.cidr}
            whitelist_cidrs := { cidr | cidr := input.parameters.cidr[_]}
            matches := net.cidr_contains_matches(whitelist_cidrs, egress_cidrs)
            matched := { cidr | cidr := matches[_][1]}
            not_matched := egress_cidrs - matched
            count(not_matched) > 0
            msg := sprintf("The network policy '%s' contains egress cidrs that are not contained in whitelist: %s", [input.review.object.metadata.name, not_matched])
        }

        violation [{"msg": msg}] {
            input.review.object.kind == "NetworkPolicy"
            not input.review.object.spec.egress[0].to
            msg := sprintf("The network policy '%s' contains an empty egress (allow all), which is not permitted.", [input.review.object.metadata.name])

        }

For those wondering how to check for errors:

kubectl describe constrainttemplate.templates.gatekeeper.sh/k8sdenyegress

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1