diff --git a/DEVELOPING.md b/DEVELOPING.md new file mode 100644 index 0000000..5bc2470 --- /dev/null +++ b/DEVELOPING.md @@ -0,0 +1,61 @@ +# Local Development + +1. Create dummy certs + +Right now the server spins up as a TLS server so we need some dummy certs. The +certs directory is configured through the `WEBHOOK_CERTS_DIR` environment +variable so you can put them wherever you want but this case just puts them in +the `./certs/` directory (which is gitignore'd). + +**IMPORTANT**: You can leave all fields blank except for the `Common Name`! Set +that to `localhost`. + +```bash +$ mkdir -p certs +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./certs/tls.key -out ./certs/tls.crt + +Generating a 2048 bit RSA private key +........+++++ +............................+++++ +writing new private key to 'tls.key' +----- +You are about to be asked to enter information that will be incorporated +into your certificate request. +What you are about to enter is what is called a Distinguished Name or a DN. +There are quite a few fields but you can leave some blank +For some fields there will be a default value, +If you enter '.', the field will be left blank. +----- +Country Name (2 letter code) []: +State or Province Name (full name) []: +Locality Name (eg, city) []: +Organization Name (eg, company) []: +Organizational Unit Name (eg, section) []: +Common Name (eg, fully qualified host name) []:localhost # MAKE SURE THIS IS localhost!! +Email Address []: +``` + +2. Run the application + +Make sure to set the `WEBHOOK_CERTS_DIR` environment variable, the default +directory is `/certs` so you'll get an error if you try to run it without +the variable + +```bash +WEBHOOK_CERTS_DIR=$PWD/certs/ cargo run +``` + +3. Interact with the server + +You can now use an http client (like curl or postman) to interact with +the server. + +```bash +curl -vk https://0.0.0.0:8443/livez +``` + +To post an admission request + +```bash +curl -k -XPOST -H'content-type: application/json' -d @data/admission.json https://0.0.0.0:8443/mutate +``` diff --git a/README.md b/README.md index caf0737..92c6db6 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,7 @@ helm upgrade --install mutate oci://ghcr.io/edera-dev/charts/protect-webhook \ ### Troubleshooting If you're running into issues, please file an issue! + +## Developing + +See [developing guide](./DEVELOPING.md) diff --git a/data/admission.json b/data/admission.json new file mode 100644 index 0000000..81099b4 --- /dev/null +++ b/data/admission.json @@ -0,0 +1,187 @@ +{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "request": { + "uid": "0cc44252-2984-4e9d-8395-bcdd4efaa329", + "kind": { + "group": "", + "version": "v1", + "kind": "Pod" + }, + "resource": { + "group": "", + "version": "v1", + "resource": "pods" + }, + "requestKind": { + "group": "", + "version": "v1", + "kind": "Pod" + }, + "requestResource": { + "group": "", + "version": "v1", + "resource": "pods" + }, + "name": "test-pod", + "namespace": "default", + "operation": "CREATE", + "userInfo": { + "username": "test", + "uid": "uid", + "groups": [ + "system:authenticated" + ], + "extra": {} + }, + "object": { + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "test-pod", + "namespace": "default", + "creationTimestamp": null, + "labels": { + "actions-ephemeral-runner": "true" + }, + "annotations": { + "dev.edera/kernel_verbose": "true", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"dev.edera/kernel_verbose\":\"true\"},\"labels\":{\"actions-ephemeral-runner\":\"true\"},\"name\":\"test-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"test-container\"}]}}\n" + }, + "managedFields": [ + { + "manager": "kubectl-client-side-apply", + "operation": "Update", + "apiVersion": "v1", + "time": "2024-12-10T16:45:35Z", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:dev.edera/kernel_verbose": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:actions-ephemeral-runner": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"test-container\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + ] + }, + "spec": { + "volumes": [ + { + "name": "kube-api-access-zdzzh", + "projected": { + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "name": "kube-root-ca.crt", + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ] + } + }, + { + "downwardAPI": { + "items": [ + { + "path": "namespace", + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + } + } + ] + } + } + ], + "defaultMode": 420 + } + } + ], + "containers": [ + { + "name": "test-container", + "image": "nginx", + "resources": {}, + "volumeMounts": [ + { + "name": "kube-api-access-zdzzh", + "readOnly": true, + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" + } + ], + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always" + } + ], + "restartPolicy": "Always", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ], + "priority": 0, + "enableServiceLinks": true, + "preemptionPolicy": "PreemptLowerPriority" + }, + "status": {} + }, + "oldObject": null, + "dryRun": false, + "options": { + "kind": "CreateOptions", + "apiVersion": "meta.k8s.io/v1", + "fieldManager": "kubectl-client-side-apply", + "fieldValidation": "Strict" + } + } +}