{"id":15486752,"url":"https://github.com/chrisns/k8s-opa-boilerplate","last_synced_at":"2025-04-22T15:26:09.021Z","repository":{"id":41967514,"uuid":"362535503","full_name":"chrisns/k8s-opa-boilerplate","owner":"chrisns","description":"Boilerplate example of managing OPA with kustomize","archived":false,"fork":false,"pushed_at":"2025-04-15T07:38:36.000Z","size":140,"stargazers_count":19,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-15T08:33:14.819Z","etag":null,"topics":["hacktoberfest","kubernetes","kustomize","opa","open-policy-agent","rego","yaml"],"latest_commit_sha":null,"homepage":"","language":"Open Policy Agent","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrisns.png","metadata":{"funding":{"github":["chrisns"],"custom":["https://www.paypal.me/cns"]},"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-04-28T16:21:49.000Z","updated_at":"2025-04-15T07:38:39.000Z","dependencies_parsed_at":"2023-09-23T18:54:42.621Z","dependency_job_id":"68d192ad-23aa-43fd-a50c-2b89d2436bfd","html_url":"https://github.com/chrisns/k8s-opa-boilerplate","commit_stats":{"total_commits":290,"total_committers":5,"mean_commits":58.0,"dds":"0.19310344827586212","last_synced_commit":"88484a94a0be18e4f87b8227e3df6ebee264f260"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisns%2Fk8s-opa-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisns%2Fk8s-opa-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisns%2Fk8s-opa-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisns%2Fk8s-opa-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisns","download_url":"https://codeload.github.com/chrisns/k8s-opa-boilerplate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250266209,"owners_count":21402250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","kubernetes","kustomize","opa","open-policy-agent","rego","yaml"],"created_at":"2024-10-02T06:09:34.284Z","updated_at":"2025-04-22T15:26:08.998Z","avatar_url":"https://github.com/chrisns.png","language":"Open Policy Agent","funding_links":["https://github.com/sponsors/chrisns","https://www.paypal.me/cns"],"categories":[],"sub_categories":[],"readme":"# Boiler plate example of managing OPA with kustomize\n\n[![Test the boilerplate](https://github.com/chrisns/k8s-opa-boilerplate/actions/workflows/test-the-boilerplate.yml/badge.svg)](https://github.com/chrisns/k8s-opa-boilerplate/actions/workflows/test-the-boilerplate.yml)\n[![Test the rego](https://github.com/chrisns/k8s-opa-boilerplate/actions/workflows/test-the-rego.yml/badge.svg)](https://github.com/chrisns/k8s-opa-boilerplate/actions/workflows/test-the-rego.yml)\n\n## Motivation\n\nI wanted a boilerplate to help me write [OPA Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website) policy documents in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/).\n\nI'm a developer that cares about testing, and general code quality so to achieve that its important to seperate the Rego from being embedded in the yaml like much of the [official documentation](https://open-policy-agent.github.io/gatekeeper/website/docs/howto) 😭\n\nI also like simplicity and sticking with vanilla tooling so rather than using the kustomize generator custom generator plugin approach I've opted for a pretty hacky stringing together of yaml to get the Rego embedded in to the `Kind: ConstraintTemplate`. Hopefully something will emerge with kustomize that allows for piping in files like how the SecretGenerator and ConfigMapGenerator work. The annoying side effect is that you end up with a pointless `ConfigMap`, you could putt his in a separate namespace to be sure it won't pollute things.\n\nI've included a test for the yaml to assert that works consistently.\n\n## Usage\n\n### Local testing\n\nI've tested this with this: (I found it was handy to prepend with `watch -n 0.5` while I was coding)\n\n```bash\n$ opa test *.rego -v --explain full\ndata.simpleRegistryCheck_test.test_mix_of_good_and_bad_images: PASS (1.025336ms)\ndata.simpleRegistryCheck_test.test_bad_images: PASS (186.052µs)\ndata.simpleRegistryCheck_test.test_good_image_no_violation: PASS (163.964µs)\ndata.simpleRegistryCheck_test.test_good_images_no_violation: PASS (256.612µs)\n--------------------------------------------------------------------------------\nPASS: 4/4\n```\n\n### Automated testing / CI\n\nTests and coverage are monitored with a [github action](./.github/workflows/test-the-rego.yaml)\n\n### Example compilation of Kubernetes resources\n\n```bash\n$ kubectl apply --dry-run=client -k . -o yaml\napiVersion: v1\nitems:\n- apiVersion: v1\n  data:\n    myrego: \"package simpleRegistryCheck\\n\\nviolation {\\n\\timage := input.request.object.spec.containers[_].image\\n\\tnot\n      startswith(image, \\\"k8s.gcr.io/\\\")\\n\\tnot startswith(image, \\\"docker.io/\\\")\\n}\\n\"\n  kind: ConfigMap\n  metadata:\n    annotations:\n      kubectl.kubernetes.io/last-applied-configuration: |\n        {\"apiVersion\":\"v1\",\"data\":{\"myrego\":\"package simpleRegistryCheck\\n\\nviolation {\\n\\timage := input.request.object.spec.containers[_].image\\n\\tnot startswith(image, \\\"k8s.gcr.io/\\\")\\n\\tnot startswith(image, \\\"docker.io/\\\")\\n}\\n\"},\"kind\":\"ConfigMap\",\"metadata\":{\"annotations\":{},\"name\":\"myrego-dk457tft5k\",\"namespace\":\"magicmirror\"}}\n    name: myrego-dk457tft5k\n    namespace: magicmirror\n- apiVersion: templates.gatekeeper.sh/v1beta1\n  kind: ConstraintTemplate\n  metadata:\n    annotations:\n      kubectl.kubernetes.io/last-applied-configuration: |\n        {\"apiVersion\":\"templates.gatekeeper.sh/v1beta1\",\"kind\":\"ConstraintTemplate\",\"metadata\":{\"annotations\":{},\"name\":\"k8strustedimages\"},\"spec\":{\"crd\":{\"spec\":{\"names\":{\"kind\":\"K8sTrustedImages\"}}},\"targets\":[{\"rego\":\"package simpleRegistryCheck\\n\\nviolation {\\n\\timage := input.request.object.spec.containers[_].image\\n\\tnot startswith(image, \\\"k8s.gcr.io/\\\")\\n\\tnot startswith(image, \\\"docker.io/\\\")\\n}\\n\",\"target\":\"admission.k8s.gatekeeper.sh\"}]}}\n    name: k8strustedimages\n  spec:\n    crd:\n      spec:\n        names:\n          kind: K8sTrustedImages\n    targets:\n    - rego: \"package simpleRegistryCheck\\n\\nviolation {\\n\\timage := input.request.object.spec.containers[_].image\\n\\tnot\n        startswith(image, \\\"k8s.gcr.io/\\\")\\n\\tnot startswith(image, \\\"docker.io/\\\")\\n}\\n\"\n      target: admission.k8s.gatekeeper.sh\nkind: List\nmetadata: {}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisns%2Fk8s-opa-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisns%2Fk8s-opa-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisns%2Fk8s-opa-boilerplate/lists"}