{"id":13499481,"url":"https://github.com/kubewarden/policy-server","last_synced_at":"2025-08-12T15:31:55.617Z","repository":{"id":36986680,"uuid":"321691643","full_name":"kubewarden/policy-server","owner":"kubewarden","description":"Webhook server that evaluates WebAssembly policies to validate Kubernetes requests","archived":false,"fork":false,"pushed_at":"2025-08-05T06:58:03.000Z","size":29808,"stargazers_count":147,"open_issues_count":21,"forks_count":20,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-08-05T08:44:45.440Z","etag":null,"topics":["hacktoberfest","kubernetes","kubernetes-security","kubernetes-webhook","policy","policy-as-code","rust","webassembly"],"latest_commit_sha":null,"homepage":"https://kubewarden.io","language":"Rust","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/kubewarden.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY-INSIGHTS.yml","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-12-15T14:26:03.000Z","updated_at":"2025-08-05T06:57:38.000Z","dependencies_parsed_at":"2023-02-19T08:35:22.304Z","dependency_job_id":"97da2e7c-05ce-4b9b-a78e-90d8fddff7e3","html_url":"https://github.com/kubewarden/policy-server","commit_stats":null,"previous_names":[],"tags_count":123,"template":false,"template_full_name":null,"purl":"pkg:github/kubewarden/policy-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubewarden%2Fpolicy-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubewarden%2Fpolicy-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubewarden%2Fpolicy-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubewarden%2Fpolicy-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kubewarden","download_url":"https://codeload.github.com/kubewarden/policy-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubewarden%2Fpolicy-server/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270086751,"owners_count":24524635,"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","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","kubernetes-security","kubernetes-webhook","policy","policy-as-code","rust","webassembly"],"created_at":"2024-07-31T22:00:33.538Z","updated_at":"2025-08-12T15:31:55.603Z","avatar_url":"https://github.com/kubewarden.png","language":"Rust","funding_links":[],"categories":["Rust","webassembly","Uncategorized"],"sub_categories":["Uncategorized"],"readme":"[![Kubewarden Core Repository](https://github.com/kubewarden/community/blob/main/badges/kubewarden-core.svg)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#core-scope)\n[![Stable](https://img.shields.io/badge/status-stable-brightgreen?style=for-the-badge)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#stable)\n[![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/kubewarden-defaults)](https://artifacthub.io/packages/helm/kubewarden/kubewarden-defaults)\n[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6626/badge)](https://bestpractices.coreinfrastructure.org/projects/6626)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/6626/badge)](https://www.bestpractices.dev/projects/6626)\n[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B25850%2Fgithub.com%2Fkubewarden%2Fpolicy-server.svg?type=shield)](https://app.fossa.com/projects/custom%2B25850%2Fgithub.com%2Fkubewarden%2Fpolicy-server?ref=badge_shield)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/kubewarden/policy-server/badge)](https://scorecard.dev/viewer/?uri=github.com/kubewarden/policy-server)\n\n\u003e **Note well:** don't forget to checkout [Kubewarden's documentation](https://docs.kubewarden.io)\n\u003e for more information\n\n# policy-server\n\n`policy-server` is a\n[Kubernetes dynamic admission controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)\nthat uses Kubewarden Policies to validate admission requests.\n\nKubewarden Policies are simple [WebAssembly](https://webassembly.org/)\nmodules.\n\n# Deployment\n\nWe recommend to rely on the [kubewarden-controller](https://github.com/kubewarden/kubewarden-controller)\nand the [Kubernetes Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)\nprovided by it to deploy the Kubewarden stack.\n\n## Configuring policies\n\nA single instance of `policy-server` can load multiple Kubewarden policies. The list\nof policies to load, how to expose them and their runtime settings are handled\nthrough a policies file.\n\nBy default `policy-server` will load the `policies.yml` file, unless the user\nprovides a different value via the `--policies` flag.\n\nThis is an example of the policies file:\n\n```yml\npsp-apparmor:\n  module: registry://ghcr.io/kubewarden/policies/psp-apparmor:v0.1.3\npsp-capabilities:\n  module: registry://ghcr.io/kubewarden/policies/psp-capabilities:v0.1.3\nnamespace_simple:\n  module: file:///tmp/namespace-validate-policy.wasm\n  settings:\n    valid_namespace: kubewarden-approved\n```\n\nThe YAML file contains a dictionary with strings as keys, and policy objects as values.\n\nThe key that identifies a policy is used by `policy-server` to expose the policy\nthrough its web interface. Policies are exposed under `/validate/\u003cpolicy id\u003e.\n\nFor example, given the configuration file from above, the following API endpoint\nwould be created:\n\n- `/validate/psp-apparmor`: this exposes the `psp-apparmor:v0.1.3`\n  policy. The Wasm module is downloaded from the OCI registry of GitHub.\n- `/validate/psp-capabilities`: this exposes the `psp-capabilities:v0.1.3`\n  policy. The Wasm module is downloaded from the OCI registry of GitHub.\n- `/validate/namespace_simple`: this exposes the `namespace-validate-policy`\n  policy. The Wasm module is loaded from a local file located under `/tmp/namespace-validate-policy.wasm`.\n\nIt's common for policies to allow users to tune their behaviour via ad-hoc settings.\nThese customization parameters are provided via the `settings` dictionary.\n\nFor example, given the configuration file from above, the `namespace_simple` policy\nwill be invoked with the `valid_namespace` parameter set to `kubewarden-approved`.\n\nNote well: it's possible to expose the same policy multiple times, each time with\na different set of parameters.\n\nThe Wasm file providing the Kubewarden Policy can be either loaded from\nthe local filesystem or it can be fetched from a remote location. The behaviour\ndepends on the URL format provided by the user:\n\n- `file:///some/local/program.wasm`: load the policy from the local filesystem\n- `https://some-host.com/some/remote/program.wasm`: download the policy from the\n  remote http(s) server\n- `registry://localhost:5000/project/artifact:some-version` download the policy\n  from a OCI registry. The policy must have been pushed as an OCI artifact\n\n### Policy Group\n\nMultiple policies can be grouped together and are evaluated using a user provided boolean expression.\n\nThe motivation for this feature is to enable users to create complex policies by combining simpler ones.\nThis allows users to avoid the need to create custom policies from scratch and instead leverage existing policies.\nThis reduces the need to duplicate policy logic across different policies, increases reusability, removes\nthe cognitive load of managing complex policy logic, and enables the creation of custom policies using\na DSL-like configuration.\n\nPolicy groups are added to the same policy configuration file as individual policies.\n\nThis is an example of the policies file with a policy group:\n\n```yml\npod-image-signatures: # policy group\n  policies:\n    - name: sigstore_pgp\n      module: ghcr.io/kubewarden/policies/verify-image-signatures:v0.2.8\n      settings:\n        signatures:\n          - image: \"*\"\n            pubKeys:\n              - \"-----BEGIN PUBLIC KEY-----xxxxx-----END PUBLIC KEY-----\"\n              - \"-----BEGIN PUBLIC KEY-----xxxxx-----END PUBLIC KEY-----\"\n    - name: sigstore_gh_action\n      module: ghcr.io/kubewarden/policies/verify-image-signatures:v0.2.8\n      settings:\n        signatures:\n          - image: \"*\"\n            githubActions:\n            owner: \"kubewarden\"\n    - name: reject_latest_tag\n      module: ghcr.io/kubewarden/policies/trusted-repos-policy:v0.1.12\n      settings:\n        tags:\n          reject:\n            - latest\n  expression: \"sigstore_pgp() || (sigstore_gh_action() \u0026\u0026 reject_latest_tag())\"\n  message: \"The group policy is rejected.\"\n```\n\nThis will lead to the exposure of a validation endpoint `/validate/pod-image-signatures`\nthat will accept the incoming request if the image is signed with the given public keys or\nif the image is built by the given GitHub Actions and the image tag is not `latest`.\n\nEach policy in the group can have its own settings and its own list of Kubernetes resources\nthat is allowed to access:\n\n```yml\nstrict-ingress-checks:\n  policies:\n    - name: unique_ingress\n      module: ghcr.io/kubewarden/policies/cel-policy:latest\n      contextAwareResources:\n        - apiVersion: networking.k8s.io/v1\n          kind: Ingress\n      settings:\n        variables:\n          - name: knownIngresses\n            expression: kw.k8s.apiVersion(\"networking.k8s.io/v1\").kind(\"Ingress\").list().items\n          - name: knownHosts\n            expression: |\n              variables.knownIngresses\n              .filter(i, (i.metadata.name != object.metadata.name) \u0026\u0026 (i.metadata.namespace != object.metadata.namespace))\n              .map(i, i.spec.rules.map(r, r.host))\n          - name: desiredHosts\n            expression: |\n              object.spec.rules.map(r, r.host)\n        validations:\n          - expression: |\n              !variables.knownHost.exists_one(hosts, sets.intersects(hosts, variables.desiredHosts))\n            message: \"Cannot reuse a host across multiple ingresses\"\n    - name: https_only\n      module: ghcr.io/kubewarden/policies/ingress:latest\n      settings:\n        requireTLS: true\n        allowPorts: [443]\n        denyPorts: [80]\n    - name: http_only\n      module: ghcr.io/kubewarden/policies/ingress:latest\n      settings:\n        requireTLS: false\n        allowPorts: [80]\n        denyPorts: [443]\n\n  expression: \"unique_ingress() \u0026\u0026 (https_only() || http_only())\"\n  message: \"The group policy is rejected.\"\n```\n\nFor more details, please refer to the Kubewarden documentation.\n\n## Logging and distributed tracing\n\nThe verbosity of policy-server can be configured via the `--log-level` flag.\nThe default log level used is `info`, but `trace`, `debug`, `warn` and `error`\nlevels are available too.\n\nPolicy server can produce logs events using different formats. The `--log-fmt`\nflag is used to choose the format to be used.\n\n### Standard output\n\nBy default, log messages are printed on the standard output using the\n`text` format. Logs can be printed as JSON objects using the `json` format type.\n\n### Open Telemetry Collector\n\nThe open Telemetry project provides a [collector](https://opentelemetry.io/docs/collector/)\ncomponent that can be used to receive, process and export telemetry data\nin a vendor agnostic way.\n\nPolicy server can send trace events to the Open Telemetry Collector using the\n`--log-fmt otlp` flag.\n\nCurrent limitations:\n\n- Traces can be sent to the collector only via grpc. The HTTP transport\n  layer is not supported.\n- The Open Telemetry Collector must be listening on localhost. When deployed\n  on Kubernetes, policy-server must have the Open Telemetry Collector\n  running as a sidecar.\n- Policy server doesn't expose any configuration setting for Open Telemetry\n  (e.g.: endpoint URL, encryption, authentication,...). All of the tuning\n  has to be done on the collector process that runs as a sidecar.\n\nMore details about OpenTelemetry and tracing can be found inside of\nour [official docs](https://docs.kubewarden.io/operator-manual/tracing/01-quickstart.html).\n\n# Building\n\nYou can use the container image we maintain inside of our\n[GitHub Container Registry](https://github.com/orgs/kubewarden/packages/container/package/policy-server).\n\nAlternatively, the `policy-server` binary can be built in this way:\n\n```shell\n$ make build\n```\n\n# Software bill of materials\n\nPolicy server has its software bill of materials (SBOM\n[SPDX](https://spdx.dev/)) and\n[Provenance](https://slsa.dev/spec/v1.0/provenance) files published every\nrelease. Both files are generated by [Docker\nbuildx](https://docs.docker.com/build/metadata/attestations/) during the build\nprocess and stored in the container registry together with the container image\nas well as uploaded to the release page. \n\nAfter the container image building, the container image and their attestations\nare signed using cosign. The attestation files are stoed inside a tarball with\nthe checksum file with the md5sum for the files there. Therefore, after\ndownloading the attestation files from the [release\npage](https://github.com/kubewarden/policy-server/releases), extracting them,\nyou can verify the checksum file signature using the following command:\n\n```shell\ncosign verify-blob --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\\n    --certificate-identity=\"https://github.com/kubewarden/policy-server/.github/workflows/attestation.yml@refs/tags/v1.17.0\" \\\n    --bundle policy-server-attestation-arm64-checksum-cosign.bundle \\\n    policy-server-attestation-arm64-checksum.txt\n```\n\nIf you want to verify the attestation manifest and its layer signatures, you\ncan use the following command:\n\n```shell\ncosign verify --certificate-oidc-issuer=https://token.actions.githubusercontent.com  \\\n    --certificate-identity=\"https://github.com/kubewarden/policy-server/.github/workflows/attestation.yml@refs/tags/v1.17.0 \\\n    ghcr.io/kubewarden/policy-server@sha256:1abc0944378d9f3ee2963123fe84d045248d320d76325f4c2d4eb201304d4c4e\n```\n\nRemember that the sha256 hash is the digest of the attestation manifest or its\nlayers. Therefore, you need to find this info in the registry using the UI or\ntools like `crane`. For example, the following command will show you all the\nattestation manifests of the `latest` tag:\n\n```shell\ncrane manifest  ghcr.io/kubewarden/policy-server:latest | jq '.manifests[] | select(.annotations[\"vnd.docker.reference.type\"]==\"attestation-manifest\")'\n{\n  \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\",\n  \"digest\": \"sha256:fc01fa6c82cffeffd23b737c7e6b153357d1e499295818dad0c7d207f64e6ee8\",\n  \"size\": 1655,\n  \"annotations\": {\n    \"vnd.docker.reference.digest\": \"sha256:611d499ec9a26034463f09fa4af4efe2856086252d233b38e3fc31b0b982d369\",\n    \"vnd.docker.reference.type\": \"attestation-manifest\"\n  },\n  \"platform\": {\n    \"architecture\": \"unknown\",\n    \"os\": \"unknown\"\n  }\n}\n{\n  \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\",\n  \"digest\": \"sha256:e0cd736c2241407114256e09a4cdeef55eb81dcd374c5785c4e5c9362a0088a2\",\n  \"size\": 1655,\n  \"annotations\": {\n    \"vnd.docker.reference.digest\": \"sha256:03e5db83a25ea2ac498cf81226ab8db8eb53a74a2c9102e4a1da922d5f68b70f\",\n    \"vnd.docker.reference.type\": \"attestation-manifest\"\n  },\n  \"platform\": {\n    \"architecture\": \"unknown\",\n    \"os\": \"unknown\"\n  }\n}\n```\n\nThen you can use the `digest` field to verify the attestation manifest and its\nlayers signatures.\n\n```shell\ncosign verify --certificate-oidc-issuer=https://token.actions.githubusercontent.com  \\\n    --certificate-identity=\"https://github.com/kubewarden/policy-server/.github/workflows/attestation.yml@refs/tags/v1.17.0 \\\n    ghcr.io/kubewarden/policy-server@sha256:fc01fa6c82cffeffd23b737c7e6b153357d1e499295818dad0c7d207f64e6ee8\n\ncrane manifest  ghcr.io/kubewarden/policy-server@sha256:fc01fa6c82cffeffd23b737c7e6b153357d1e499295818dad0c7d207f64e6ee8\n{\n  \"schemaVersion\": 2,\n  \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\",\n  \"config\": {\n    \"mediaType\": \"application/vnd.oci.image.config.v1+json\",\n    \"digest\": \"sha256:eda788a0e94041a443eca7286a9ef7fce40aa2832263f7d76c597186f5887f6a\",\n    \"size\": 463\n  },\n  \"layers\": [\n    {\n      \"mediaType\": \"application/vnd.in-toto+json\",\n      \"digest\": \"sha256:563689cdee407ab514d057fe2f8f693189279e10bfe4f31f277e24dee00793ea\",\n      \"size\": 94849,\n      \"annotations\": {\n        \"in-toto.io/predicate-type\": \"https://spdx.dev/Document\"\n      }\n    },\n    {\n      \"mediaType\": \"application/vnd.in-toto+json\",\n      \"digest\": \"sha256:7ce0572628290373e17ba0bbb44a9ec3c94ba36034124931d322ca3fbfb768d9\",\n      \"size\": 7363045,\n      \"annotations\": {\n        \"in-toto.io/predicate-type\": \"https://spdx.dev/Document\"\n      }\n    },\n    {\n      \"mediaType\": \"application/vnd.in-toto+json\",\n      \"digest\": \"sha256:dacf511c5ec7fd87e8692bd08c3ced2c46f4da72e7271b82f1b3720d5b0a8877\",\n      \"size\": 71331,\n      \"annotations\": {\n        \"in-toto.io/predicate-type\": \"https://spdx.dev/Document\"\n      }\n    },\n    {\n      \"mediaType\": \"application/vnd.in-toto+json\",\n      \"digest\": \"sha256:594da3e8bd8c6ee2682b0db35857933f9558fd98ec092344a6c1e31398082f4d\",\n      \"size\": 980,\n      \"annotations\": {\n        \"in-toto.io/predicate-type\": \"https://spdx.dev/Document\"\n      }\n    },\n    {\n      \"mediaType\": \"application/vnd.in-toto+json\",\n      \"digest\": \"sha256:7738d8d506c6482aaaef1d22ed920468ffaf4975afd28f49bb50dba2c20bf2ca\",\n      \"size\": 13838,\n      \"annotations\": {\n        \"in-toto.io/predicate-type\": \"https://slsa.dev/provenance/v0.2\"\n      }\n    }\n  ]\n}\n\ncosign verify --certificate-oidc-issuer=https://token.actions.githubusercontent.com  \\\n    --certificate-identity=\"https://github.com/kubewarden/policy-server/.github/workflows/attestation.yml@refs/tags/v1.17.0 \\\n    ghcr.io/kubewarden/policy-server@sha256:594da3e8bd8c6ee2682b0db35857933f9558fd98ec092344a6c1e31398082f4d\n```\n\nNote that each attestation manifest (for each architecture) has its own layers.\nEach layer is a different SBOM SPDX or provenance files generated by Docker\nBuildx during the multi stage build process. You can also use `crane` to\ndownload the attestation file:\n\n```shell\ncrane blob ghcr.io/kubewarden/policy-server@sha256:7738d8d506c6482aaaef1d22ed920468ffaf4975afd28f49bb50dba2c20bf2ca\n```\n\n# Security\n\nThe Kubewarden team is security conscious. You can find our [threat model\nassessment](https://docs.kubewarden.io/security/threat-model) and\n[responsible disclosure approach](https://docs.kubewarden.io/security/disclosure)\nin our Kubewarden docs.\n\n## Changelog\n\nSee [GitHub Releases content](https://github.com/kubewarden/policy-server/releases).\n\n# CLI documentation\n\nIf you want a complete list of the available commands, you can read the \n[cli-docs.md](./cli-docs.md) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkubewarden%2Fpolicy-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkubewarden%2Fpolicy-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkubewarden%2Fpolicy-server/lists"}