Skip to content

Commit 9016ad9

Browse files
WIP: Docs
1 parent aadcc7c commit 9016ad9

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

README.md

+109-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,115 @@
1-
# opa-k8s-development
2-
Contains a valid OPA unit testing environment
1+
# OPA Kubernetes validation and mutation testing environment
2+
3+
![OPA Logo](./assets/opa.png)
4+
5+
This project makes easy to develop `deny` rules and `patches` mutations. In this repository you will find a `main.rego` file wich is in charge of generate the expected Kubernetes API `json` response in the Validation and mutation stage a long with a set of basic `deny` rules and it's tests + mocks.
36

47
## TL;DR
58

69
```bash
710
$ opa test -v .
11+
[angel@elitebook opa-k8s-development]$ opa test -v .
12+
data.kubernetes.admission.test_create_ingress_existing_in_other_namespace: PASS (719.34µs)
13+
data.kubernetes.admission.test_create_client_valid_ingress: PASS (503.277µs)
14+
data.system.test_default_response: PASS (495.764µs)
15+
data.kubernetes.admission.test_invalid_client_pod_priorityclass: PASS (527.651µs)
16+
data.kubernetes.admission.test_valid_client_pod_priorityclass: PASS (472.089µs)
17+
--------------------------------------------------------------------------------
18+
PASS: 5/5
19+
20+
```
21+
22+
## OPA Webhooks
23+
24+
OPA and Kubernetes has to be configured registering a validation and mutation webhook into Kubernetes API. This topic is out of the scope of this project but you can read more about it in the [official OPA documentation](https://www.openpolicyagent.org/docs/latest/kubernetes-admission-control).
25+
26+
But, you have to keep in your mind the following diagram:
27+
28+
![Kubernetes Request FLOW](./assets/flow.png)
29+
30+
The important thing here is to know that the mutation phase is triggered before the validation one.
31+
32+
## Project structure
33+
34+
This repository contains three different tpyes of rego files to make it easy to extend this environment:
35+
36+
- `[KIND].rego`: This files contains the `deny` or `pathes` rules to validate or mutate a request.
37+
- `[KIND]-test.rego`: This ones contains a set of test related to the testing kind specified in it's name.
38+
- `[KIND]-mocks.rego`: This files contains a series of Kubernetes requests to use as mocked requests in tests.
39+
40+
There are also a couple of special rego files:
41+
42+
- `main.rego` and `main-test.rego`: Contains the structures to build the kubernetes api responses used to validate and mutate the incoming requests.
43+
44+
### main.rego
45+
46+
```rego
47+
package system
48+
49+
import data.kubernetes.admission
50+
51+
main = {
52+
"apiVersion": "admission.k8s.io/v1beta1",
53+
"kind": "AdmissionReview",
54+
"response": response,
55+
}
56+
57+
default response = {"allowed": true}
58+
59+
response = {
60+
"allowed": false,
61+
"status": {"reason": reason},
62+
} {
63+
reason := concat(", ", admission.deny)
64+
reason != ""
65+
}
66+
67+
response = {
68+
"allowed": true,
69+
"patchType": "JSONPatch",
70+
"patch": patch_bytes,
71+
} {
72+
reason := concat(", ", admission.deny)
73+
reason == ""
74+
patch := {xw | xw := admission.patches[_][_]}
75+
patch_json := json.marshal(patch)
76+
patch_bytes := base64.encode(patch_json)
77+
}
78+
```
79+
80+
Let's review this **important** file. The `main` structure contains the common part of a validate and mutate response. In the `main` structure it's present a `response` attribute. This attribute will get three different values depending of the rules (deny and patches) applied to the incoming requests:
81+
82+
- If no deny and no patches applied to the incoming request, it will use the `default response`.
83+
- If not deny rules applied, `reason == ""`, the response will be `"patchType": "JSONPatch",` with the patches applyed to the request *(Can be empty)*.
84+
- If some deny rules returned a reason, `reason != ""`, the response will be `"allowed": false, "status": {"reason": reason},`. The client will get the reason message in the response.
85+
86+
It's really important to know that the same input has to generate only one output. OPA Allows a function to return two different outputs, but kubernetes only accepts one. This is the reason why both (non default) response structure are exclusive using the `reason empty comparation`.
87+
88+
89+
## Using it
90+
91+
To use this testing environment you will need to clone this repository and download the latest [OPA](https://www.openpolicyagent.org/) release *(actual version: [v0.13.5](https://github.com/open-policy-agent/opa/releases/tag/v0.13.5))*. It's not needed to have a kubernetes cluster. Remember, this project is useful in the [OPA](https://www.openpolicyagent.org/) rules/mutations development stage.
92+
93+
94+
The following commands has been executed in a [`centos:7` container image](https://hub.docker.com/_/centos?tab=tags) to make it repeatable and cleaner:
95+
```bash
96+
$ docker run -it --rm centos:7 /bin/bash
97+
[root@d8997b63a370 /]# yum install -y wget git # Output hidden
98+
[root@d8997b63a370 /]# git clone https://github.com/k8spin/opa-k8s-development.git
99+
Cloning into 'opa-k8s-development'...
100+
remote: Enumerating objects: 26, done.
101+
remote: Counting objects: 100% (26/26), done.
102+
remote: Compressing objects: 100% (20/20), done.
103+
remote: Total 26 (delta 10), reused 19 (delta 5), pack-reused 0
104+
Unpacking objects: 100% (26/26), done.
105+
[root@d8997b63a370 /]# wget -q https://github.com/open-policy-agent/opa/releases/download/v0.13.5/opa_linux_amd64 -O opa
106+
[root@d8997b63a370 /]# chmod +x opa
107+
[root@d8997b63a370 /]# ./opa test -v opa-k8s-development/
108+
data.kubernetes.admission.test_create_ingress_existing_in_other_namespace: PASS (748.309µs)
109+
data.kubernetes.admission.test_create_client_valid_ingress: PASS (522.186µs)
110+
data.system.test_default_response: PASS (550.857µs)
111+
data.kubernetes.admission.test_invalid_client_pod_priorityclass: PASS (520.333µs)
112+
data.kubernetes.admission.test_valid_client_pod_priorityclass: PASS (609.106µs)
113+
--------------------------------------------------------------------------------
114+
PASS: 5/5
8115
```

assets/flow.png

28.7 KB
Loading

assets/opa.png

118 KB
Loading

0 commit comments

Comments
 (0)