{"id":19326618,"url":"https://github.com/thought-machine/generic-k8s-webhook","last_synced_at":"2026-05-18T05:33:21.586Z","repository":{"id":175630902,"uuid":"653239516","full_name":"thought-machine/generic-k8s-webhook","owner":"thought-machine","description":"Configurable webhook that can implement multiple validators and mutators using a simple yaml config file","archived":false,"fork":false,"pushed_at":"2025-01-16T16:19:07.000Z","size":126,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":26,"default_branch":"main","last_synced_at":"2025-01-16T17:43:19.782Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thought-machine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-13T17:02:11.000Z","updated_at":"2025-01-16T16:16:33.000Z","dependencies_parsed_at":"2024-05-04T20:28:58.963Z","dependency_job_id":"c94e990b-9a00-48e3-87e3-d4ff1a1ff4de","html_url":"https://github.com/thought-machine/generic-k8s-webhook","commit_stats":null,"previous_names":["jordipiqueselles/generic-k8s-webhook","thought-machine/generic-k8s-webhook"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thought-machine%2Fgeneric-k8s-webhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thought-machine%2Fgeneric-k8s-webhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thought-machine%2Fgeneric-k8s-webhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thought-machine%2Fgeneric-k8s-webhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thought-machine","download_url":"https://codeload.github.com/thought-machine/generic-k8s-webhook/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240427460,"owners_count":19799498,"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":[],"created_at":"2024-11-10T02:14:20.072Z","updated_at":"2026-05-18T05:33:21.555Z","avatar_url":"https://github.com/thought-machine.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# generic-k8s-webhook\n\nConfigurable K8S webhook that can implement multiple validators and mutators using a simple yaml config file.\n\nFor example, this is the config to validate that no `serviceaccount` uses the `kube-system` namespace. This validator can be accessed on `\u003chostname\u003e:\u003cport\u003e/check-namespace-sa`.\n\n```yaml\napiVersion: generic-webhook/v1beta1\nkind: GenericWebhookConfig\nwebhooks:\n  - name: check-namespace-sa\n    path: /check-namespace-sa\n    actions:\n      # Refuse the request if it's a ServiceAccount that\n      # is placed on the \"kube-system\" namespace\n      - condition: .metadata.namespace == \"kube-system\" \u0026\u0026 .kind == \"ServiceAccount\"\n        accept: false\n```\n\n## Why should you use the `generic-k8s-webhook`?\n\nWith this project, you can **avoid writing from scratch simple K8S Validating or Mutating webhooks**. The logic of the webhook can be written in a simple yaml configuration file. Moreover, this **yaml config can be changed dynamically** without the need of restarting the app.\n\nApart from that, it also allows you to maintain **a single K8S deployment for all your webhooks** instead of having to maintain a separate deployment for each webhook. This is possible because the `GenericWebhookConfig` config file accepts multiple webhook configs, each listening to a different path.\n\n## Deploying the generic webhook to K8S\n\nYou need (at least) the following resources:\n\n- deployment\n- service\n- configmap\n\nThe `configmap` should contain the `GenericWebhookConfig`.\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  [...]\ndata:\n  generic-webhook-config: |\n    apiVersion: generic-webhook/v1beta1\n    kind: GenericWebhookConfig\n    webhooks:\n      - ...\n      - ...\n```\n\nThe pod template within the `deployment` should mount the previous config map as a file. Finally, in the same pod template, we should pass `--config \u003cpath-to-mounted-generic-webhook-config-file\u003e` and `--port \u003cport\u003e` as `args` for the container.\n\n## The `GenericWebhookConfig` config file\n\nThis file allows the user to configure several webhooks in a single app. In this section, we'll see the structure and syntax that it follows.\n\nThe [examples](./examples/) directory contains a fair amount of examples to help the user better understand how they can leverage the `GenericWebhookConfig` to write their own Validating or Mutating webhooks.\n\n```yaml\napiVersion: generic-webhook/v1beta1\nkind: GenericWebhookConfig\nwebhooks:\n  - # Configuration for the first webhook\n\n  - # Configuration for the second webhook\n\n  ...\n```\n\nThe structure of the configuration of a webhook (an entry in the `webhooks` list) is the following:\n\n```yaml\n# Name used to identify this webhook\nname: \u003cname\u003e\n# Path where this webhook will listen (\u003chostname\u003e:\u003cport\u003e/\u003cpath\u003e)\npath: \u003cpath\u003e\n# The actions (accept and/or patch) this webhook will perform\nactions:\n  - # The condition that must be met to execute this action. The condition\n    # is evaluated based on the K8S manifest that the K8S control plane sends\n    # to this app.\n    # For example, \"the manifest defines a pod and this pod defines request.cpu\"\n    condition: {}\n    # [ACTION] Whether to accept or not the manifest sent by the K8S control plane\n    # If not specified, it defaults to true\n    accept: true | false\n    # [ACTION] The patch to apply to the manifest. If set, then the webhook behaves\n    # as a Mutating webhook\n    patch: []\n\n  - ...\n\n```\n\nIf more than one webhook have the same path, they will be called in order. The `accept` responses are ANDed and the `patch` responses are concatenated. Notice that a given webhook will receive the payload already modified by all the previous webhooks that have the same path.\n\nThe syntax of the `condition` can be found in [Defining a condition](#defining-a-condition). The syntax of the patch can be found in [Defining a patch](#defining-a-patch).\n\n### Testing the `GenericWebhookConfig` file is correct\n\nIt can be frustrating to deploy a change in the `configmap` that contains the `GenericWebhookConfig` just to see that it's not working as expected. For this reason, it's advisable to test new configurations in advance. That's why this app can be invoked as a cli tool.\n\nAssuming you've cloned the repo and you have [poetry](https://python-poetry.org/docs/) installed.\n\n```bash\npoetry run python3 generic_k8s_webhook/main.py --config \u003cpath-to-GenericWebhookConfig-file\u003e cli --k8s-manifest \u003ck8s-manifest-to-analise\u003e --wh-name \u003cwebhook-to-use\u003e\n```\n\nThe value of the `--config` argument is the path of the `GenericWebhookConfig` config file. The value of the `--k8s-manifest` argument is a K8S manifest file that will be processed by the webhook. The value of the `--wh-name` is just the name of the webhook that we'll use to process the manifest. Remember that we can have several webhooks in the same app.\n\n### Defining a condition\n\nThe conditions can be defined using structured operators and/or a simple pseudolanguage. For example, the following condition combines both a structured operator (an `and`) and a couple of lines of this pseudolanguage.\n\n```yaml\nand:\n  - .kind == \"Pod\"\n  - .metadata.labels.latencyCritical == true \u0026\u0026 .metadata.labels.app == \"backend\"\n```\n\nWe can also iterate over lists and nested lists. In the following example, we check that a pod has at least one container called \"main\".\n\n```yaml\nany: .spec.containers.* -\u003e .name == \"main\"\n```\n\nThe `*` is used to iterate over a list, in that case the list of containers. The `-\u003e` operator is like a map. So, assuming the pod has two containers, one named \"main\" and the other named \"foo\", the `.spec.containers.* -\u003e .name == \"main\"` returns `[true, false]`.\n\nYou can check [operators-reference](./docs/operators-reference.md) to see all the available structured operators.\n\n### Defining a patch\n\nThe patch is defined almost in the same as a standard [jsonpatch](https://jsonpatch.com/). The only difference is that, when defining a path, instead of using `/` to separate its components, we use `.`.\n\n```yaml\npatch:\n  - op: add\n    path: .metadata.labels\n    value: \u003cany value\u003e\n```\n\n## Next steps\n\n- Script to measure performance (API calls per second) for a single replica\n- Create a CRD for the `GenericWebhookConfig` and consume it as a K8S object instead of as a ConfigMap\n- Add more examples\n- Helm chart\n- Analyse how much CPU and memory the app needs\n- Prometheus metrics to show number of requests processed, succeeded, queued requests, time it takes to process a request, etc.\n\n## Contributing\n\nSee the [contributor guide](./docs/contributor-guide.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthought-machine%2Fgeneric-k8s-webhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthought-machine%2Fgeneric-k8s-webhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthought-machine%2Fgeneric-k8s-webhook/lists"}