In this series of blog posts, we will be looking at deploying OPA gatekeeper as the admission controller for our Kubernetes cluster. We will be focusing specifically at creating gatekeeper policies for networking inside the Kubernetes cluster.
If you want to know how the Audit logs are sent to EFK, you can read the following article on sending the logs to EFK.
Aim:
Write a gatekeeper policy which denies anyone, trying to apply any kind of ingress/egress acesss to any IP or IP CIDR ranges except the ones which are allowed.
Template.yaml
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." }
Understanding the REGO policy,
- In this template, we have defined a parameter in the ‘OPENAPIV3SCHEMA’. This parameter is of type array and data type string. The parameter will be included in our constraint file.
- ‘input.review.object.kind == “NetworkPolicy” ‘ (Checks if the kind if NetworkPolicy)
- Next, we take a variable cidr_or_ip and save the value of the IP CIDR provided in the NetworkPolicy.yaml.
- Next, a variable cidr which stores the value of IP CIDR provided in the constraints file.
- The Value cidr will store the result of ‘net.cidr_contains’ function.
- net.cidr_contains(cidr,cidr_or_ip) is an inbuilt function in rego. CIDR will contain the allowed range and cidr_or_ip will contain the cidr or ip we want. It will check the value against cidr, and if it exists in the range, it will return true.
constraint.yaml
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"
Since, we defined a parameter in our template file, we will be including it in the parameters label. We have provided the IP CIDR of 192.168.0.1/24.
NetworkPolicy Deny :
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-external spec: podSelector: {} policyTypes: - Egress - Ingress egress: - to: - ipBlock: cidr: 192.168.1.45/32

NetworkPolicy Allow :
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-external spec: podSelector: {} policyTypes: - Egress - Ingress egress: - to: - ipBlock: cidr: 192.168.0.45/32

The Same can be used for ingress with some changes to the REGO code. We can use the following code in rego to get the Ipblock.
‘input.review.object.spec.ingress[_].from[_].ipBlock.cidr’
Conclusion :
This was a very basic example of applying OPA gatekeeper, to deny anyone trying to allow ingress/egress access to an IP or IP CIDR range which is not allowed.
Other related articles:
- OPA Gatekeeper Audit and Logging using EFK
- A Series of Blog Posts on using OPA Policies & Gatekeeper for Kubernetes Security
Practice here:
https://www.katacoda.com/cloudsecops/courses/opagatekeeper-policy/configmap
References:
- https://github.com/open-policy-agent/gatekeeper
- https://github.com/open-policy-agent/gatekeeper-library
Thank you for reading! – Siddarth Tanna and Setu Parimi
Sign up for the blog directly here.
Check out our professional services here.
Feedback is welcome! For professional services, fan mail, hate mail, or whatever else, contact [email protected]
0 Comments