{"id":48300629,"url":"https://github.com/devopstales/trivy-operator","last_synced_at":"2026-04-04T23:46:18.412Z","repository":{"id":37719221,"uuid":"412815465","full_name":"devopstales/trivy-operator","owner":"devopstales","description":"Kubernetes Operator based on the open-source container vulnerability scanner Trivy.","archived":false,"fork":false,"pushed_at":"2025-06-11T09:03:31.000Z","size":46674,"stargazers_count":47,"open_issues_count":11,"forks_count":10,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-11T10:25:42.760Z","etag":null,"topics":["admission-control","admission-controlers","admission-controller","kopf","kubernetes","kubernetes-operator","kubernetes-operators","operator","python","python-kubernetes","python3","trivy"],"latest_commit_sha":null,"homepage":"https://devopstales.github.io/trivy-operator/","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/devopstales.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,"zenodo":null}},"created_at":"2021-10-02T14:12:11.000Z","updated_at":"2024-09-16T20:29:05.000Z","dependencies_parsed_at":"2023-02-16T10:15:45.033Z","dependency_job_id":"95a7e38c-d576-40b9-8929-4096ecdbbe30","html_url":"https://github.com/devopstales/trivy-operator","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/devopstales/trivy-operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devopstales%2Ftrivy-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devopstales%2Ftrivy-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devopstales%2Ftrivy-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devopstales%2Ftrivy-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devopstales","download_url":"https://codeload.github.com/devopstales/trivy-operator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devopstales%2Ftrivy-operator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31419545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["admission-control","admission-controlers","admission-controller","kopf","kubernetes","kubernetes-operator","kubernetes-operators","operator","python","python-kubernetes","python3","trivy"],"created_at":"2026-04-04T23:46:14.482Z","updated_at":"2026-04-04T23:46:18.386Z","avatar_url":"https://github.com/devopstales.png","language":"Python","readme":"# Trivy Operator\n\nThe goal of this project is to provide a vulnerability scanner that continuously scans containers deployed in a Kubernetes cluster. Built with [kopf](https://github.com/nolar/kopf)\n\n\nIt works as \n- Operator\n  - Scheduled Image scans on running pods\n- Admission Controller\n  - protecting unsafe images from being deployed\n\nInspirated by [knqyf263](https://github.com/knqyf263)'s [trivy-enforcer](https://github.com/aquasecurity/trivy-enforcer) and [fleeto](https://github.com/fleeto)'s [trivy-scanner](https://github.com/fleeto/trivy-scanner).\n\n### Scheduled Image scans\nDefault trivy-operator execute a scan script every 5 minutes. It will get images from all the namespaces with the label `trivy-scan=true`, and then check these images with trivy for vulnerabilities. Finally we will get metrics on `http://[pod-ip]:9115/metrics`\n\n### Trivy Image Validator\nThe admission controller function can be configured as a ValidatingWebhook in a k8s cluster. Kubernetes will send requests to the admission server when a Pod creation is initiated. The admission controller checks the image using trivy if it is in a namespace with the label `trivy-operator-validation=true`.\n\n## Install\n\nUser the [helm Chert](https://github.com/devopstales/helm-charts)\n\n## Usage\n\n```bash\nkubectl label namespaces guestbook-demo trivy-scan=true\nkubectl label namespaces guestbook-demo trivy-operator-validation=true\n# or\nkubectl apply -f deploy/kubernetes/10_demo.yaml\n\nkubectl apply -f deploy/kubernetes/04_trivy-config.yaml\n```\n\n~~~text\ncurl -s http://10.43.179.39:9115/metrics | grep trivy_vulnerabilities\n# HELP trivy_vulnerabilities_sum Container vulnerabilities\n# TYPE trivy_vulnerabilities_sum gauge\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/openshift/mysql-56-centos7:latest\",severity=\"scanning_error\"} 1.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",severity=\"UNKNOWN\"} 0.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",severity=\"LOW\"} 83.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",severity=\"MEDIUM\"} 5.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",severity=\"HIGH\"} 7.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",severity=\"CRITICAL\"} 4.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/library/nginx:1.18\",severity=\"UNKNOWN\"} 0.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/library/nginx:1.18\",severity=\"LOW\"} 126.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/library/nginx:1.18\",severity=\"MEDIUM\"} 25.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/library/nginx:1.18\",severity=\"HIGH\"} 43.0\ntrivy_vulnerabilities_sum{exported_namespace=\"trivytest\",image=\"docker.io/library/nginx:1.18\",severity=\"CRITICAL\"} 21.0\n# HELP trivy_vulnerabilities Container vulnerabilities\n# TYPE trivy_vulnerabilities gauge\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"2.2.4\",pkgName=\"pkgName\",severity=\"LOW\",vulnerabilityId=\"CVE-2011-3374\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"8.32-4\",pkgName=\"pkgName\",severity=\"LOW\",vulnerabilityId=\"CVE-2016-2781\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"8.32-4\",pkgName=\"pkgName\",severity=\"LOW\",vulnerabilityId=\"CVE-2017-18018\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"7.74.0-1.3\",pkgName=\"pkgName\",severity=\"CRITICAL\",vulnerabilityId=\"CVE-2021-22945\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"7.74.0-1.3\",pkgName=\"pkgName\",severity=\"HIGH\",vulnerabilityId=\"CVE-2021-22946\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"7.74.0-1.3\",pkgName=\"pkgName\",severity=\"MEDIUM\",vulnerabilityId=\"CVE-2021-22947\"} 1.0\ntrivy_vulnerabilities{exported_namespace=\"trivytest\",image=\"docker.io/nginxinc/nginx-unprivileged:latest\",installedVersion=\"7.74.0-1.3\",pkgName=\"pkgName\",severity=\"LOW\",vulnerabilityId=\"CVE-2021-22898\"} 1.0\n~~~\n\n~~~text\ncurl -s http://10.43.179.39:9115/metrics | grep ac_vulnerabilities\n\n# HELP ac_vulnerabilities Admission Controller vulnerabilities\n# TYPE ac_vulnerabilities gauge\nac_vulnerabilities{exported_namespace=\"trivytest\",image=\"nginxinc/nginx-unprivileged:latest\",severity=\"UNKNOWN\"} 0.0\nac_vulnerabilities{exported_namespace=\"trivytest\",image=\"nginxinc/nginx-unprivileged:latest\",severity=\"LOW\"} 83.0\nac_vulnerabilities{exported_namespace=\"trivytest\",image=\"nginxinc/nginx-unprivileged:latest\",severity=\"MEDIUM\"} 6.0\nac_vulnerabilities{exported_namespace=\"trivytest\",image=\"nginxinc/nginx-unprivileged:latest\",severity=\"HIGH\"} 6.0\nac_vulnerabilities{exported_namespace=\"trivytest\",image=\"nginxinc/nginx-unprivileged:latest\",severity=\"CRITICAL\"} 4.0\n~~~\n\n\n~~~text\nkubectl logs \n\n[2021-10-02 09:38:38,598] kopf.activities.star [INFO    ] Activity 'startup_fn_crd' succeeded.\n[2021-10-02 09:38:38,687] kopf.activities.star [INFO    ] trivy cache created...\n[2021-10-02 09:38:38,687] kopf.activities.star [INFO    ] Activity 'startup_fn_trivy_cache' succeeded.\n[2021-10-02 09:38:38,689] kopf._core.engines.a [INFO    ] Initial authentication has been initiated.\n[2021-10-02 09:38:38,696] kopf.activities.auth [INFO    ] Activity 'login_via_client' succeeded.\n[2021-10-02 09:38:38,697] kopf._core.engines.a [INFO    ] Initial authentication has finished.\n[2021-10-02 09:38:46,726] kopf.objects         [INFO    ] [trivytest/main-config] Prometheus Exporter started...\n[2021-10-02 09:40:01,831] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:40:05,245] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n[2021-10-02 09:40:23,817] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:40:26,947] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n[2021-10-02 09:40:45,428] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:40:48,949] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n\n[2021-10-02 09:45:08,229] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:45:11,922] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n[2021-10-02 09:45:30,381] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:45:33,881] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n[2021-10-02 09:45:52,227] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:1.18\n[2021-10-02 09:45:55,556] kopf.objects         [INFO    ] [trivytest/main-config] Scanning Image: docker.io/library/nginx:latest\n\n[2021-10-02 18:33:32,742] kopf.objects         [INFO    ] [trivytest/app-85ddd4585b-sdt4t] Admission Controller is working\n[2021-10-02 18:33:32,755] kopf.objects         [INFO    ] [trivytest/app-85ddd4585b-sdt4t] Scanning Image: nginxinc/nginx-unprivileged:latest\n[2021-10-02 18:33:34,967] kopf.objects         [INFO    ] [trivytest/app-85ddd4585b-sdt4t] severity: {'UNKNOWN': 0, 'LOW': 83, 'MEDIUM': 6, 'HIGH':6, 'CRITICAL': 4}\n[2021-10-02 18:33:34,969] kopf.objects         [ERROR   ] [trivytest/app-85ddd4585b-sdt4t] Webhook 'validate1' failed permanently: Too muchvulnerability in the image: nginxinc/nginx-unprivileged:latest\n[2021-10-02 18:33:34,971] aiohttp.access       [INFO    ] 10.244.0.1 [17/Dec/2021:18:33:32 +0000] \"POST /validate1?timeout=30s HTTP/1.1\" 200 417\"-\" \"kube-apiserver-admission\"\n~~~\n\n### Example Deploy:\nYou can define policy to the Admission Controller, by adding annotation to the pod through the deployment:\n\n```yaml\nspec:\n  ...\n  template:\n    metadata:\n      annotations:\n        trivy.security.devopstales.io/medium: \"5\"\n        trivy.security.devopstales.io/low: \"10\"\n        trivy.security.devopstales.io/critical: \"2\"\n...\n```\n\n### Development\n\nInstall trivy:\n\n```bash\nnano /etc/yum.repos.d/trivy.repo\n[trivy]\nname=Trivy repository\nbaseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/\ngpgcheck=0\nenabled=1\n\nsudo yum -y install trivy\n```\n\nTo run kopf development you need to install the fallowing packages to the k3s host:\n\n```bash\nyum install -y python3.8\npip3 install --no-cache-dir kopf[dev] kubernetes asyncio pycron prometheus_client oscrypto certvalidator certbuilder validators pyOpenSSL\n```\n\nThe admission webhook try to call the host with the domain name `host.k3d.internal` so I added to the host's `/etc/host` file.\n\n```bash\necho \"172.17.12.10 host.k3d.internal\" \u003e\u003e /etc/host\n```\n\n```bash\nkopf run -A ./trivy-operator.py\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevopstales%2Ftrivy-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevopstales%2Ftrivy-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevopstales%2Ftrivy-operator/lists"}