{"id":13819855,"url":"https://github.com/smallstep/autocert","last_synced_at":"2026-04-01T18:19:28.946Z","repository":{"id":38010741,"uuid":"190796273","full_name":"smallstep/autocert","owner":"smallstep","description":"⚓ A kubernetes add-on that automatically injects TLS/HTTPS certificates into your containers","archived":false,"fork":false,"pushed_at":"2026-03-19T06:02:15.000Z","size":13448,"stargazers_count":791,"open_issues_count":17,"forks_count":65,"subscribers_count":21,"default_branch":"master","last_synced_at":"2026-03-19T13:57:37.426Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","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/smallstep.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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-06-07T19:12:12.000Z","updated_at":"2026-03-19T04:51:34.000Z","dependencies_parsed_at":"2023-10-16T22:42:34.609Z","dependency_job_id":"d7b8a945-d7e8-4823-a21a-f5b3b8a19062","html_url":"https://github.com/smallstep/autocert","commit_stats":{"total_commits":116,"total_committers":15,"mean_commits":7.733333333333333,"dds":0.7241379310344828,"last_synced_commit":"681561a6f639dcd801918dd6e7ab93ce83078a41"},"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"purl":"pkg:github/smallstep/autocert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallstep%2Fautocert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallstep%2Fautocert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallstep%2Fautocert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallstep%2Fautocert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smallstep","download_url":"https://codeload.github.com/smallstep/autocert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smallstep%2Fautocert/sbom","scorecard":{"id":832462,"data":{"date":"2025-08-11","repo":{"name":"github.com/smallstep/autocert","commit":"afac7f5c3b4dd1696039b1705fab6441f5353203"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.4,"checks":[{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":-1,"reason":"Found no human activity in the last 15 changesets","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/ci.yml:22","Info: jobLevel 'contents' permission set to 'read': .github/workflows/ci.yml:23","Warn: jobLevel 'security-events' permission set to 'write': .github/workflows/ci.yml:24","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:76","Warn: jobLevel 'packages' permission set to 'write': .github/workflows/release.yml:77","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:86","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:100","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:114","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:128","Warn: topLevel 'contents' permission set to 'write': .github/workflows/actionlint.yml:11","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/code-scan-cron.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/dependabot-auto-merge.yml:5","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/triage.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":8,"reason":"5 out of the last 5 releases have a total of 5 signed artifacts.","details":["Info: signed release artifact: autocert_0.20.2-rc1.tar.gz.sig: https://github.com/smallstep/autocert/releases/tag/v0.20.2-rc1","Info: signed release artifact: autocert_0.20.2.tar.gz.sig: https://github.com/smallstep/autocert/releases/tag/v0.20.2","Info: signed release artifact: autocert_0.20.1-rc4.tar.gz.sig: https://github.com/smallstep/autocert/releases/tag/v0.20.1-rc4","Info: signed release artifact: autocert_0.20.1.tar.gz.sig: https://github.com/smallstep/autocert/releases/tag/v0.20.1","Info: signed release artifact: autocert_0.20.1-rc3.tar.gz.sig: https://github.com/smallstep/autocert/releases/tag/v0.20.1-rc3","Warn: release artifact v0.20.2-rc1 does not have provenance: https://api.github.com/repos/smallstep/autocert/releases/232296974","Warn: release artifact v0.20.2 does not have provenance: https://api.github.com/repos/smallstep/autocert/releases/232300794","Warn: release artifact v0.20.1-rc4 does not have provenance: https://api.github.com/repos/smallstep/autocert/releases/206690333","Warn: release artifact v0.20.1 does not have provenance: https://api.github.com/repos/smallstep/autocert/releases/206702156","Warn: release artifact v0.20.1-rc3 does not have provenance: https://api.github.com/repos/smallstep/autocert/releases/199972308"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: all commits (30) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2018-66 / GHSA-562c-5r94-xh97","Warn: Project is vulnerable to: PYSEC-2019-179 / GHSA-5wv5-4vpf-pj6m","Warn: Project is vulnerable to: PYSEC-2023-62 / GHSA-m2qf-hxjv-5gpq","Warn: Project is vulnerable to: PYSEC-2018-55 / GHSA-32pc-xphx-q4f6","Warn: Project is vulnerable to: GHSA-hc5x-x2vx-497g","Warn: Project is vulnerable to: GHSA-w3h3-4rj7-4ph4"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/actionlint.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/actionlint.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/code-scan-cron.yml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/code-scan-cron.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dependabot-auto-merge.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/dependabot-auto-merge.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:101: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:115: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:129: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/triage.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/smallstep/autocert/triage.yml/master?enable=pin","Warn: containerImage not pinned by hash: bootstrapper/Dockerfile:1: pin your Docker image by updating smallstep/step-cli:0.26.0 to smallstep/step-cli:0.26.0@sha256:7e21dd9f07cdf7993e99905ee331b7bcc25f46ac5c4b3a7efb586bb8f786c122","Warn: containerImage not pinned by hash: controller/Dockerfile:2","Warn: containerImage not pinned by hash: controller/Dockerfile:12: pin your Docker image by updating smallstep/step-cli:0.26.0 to smallstep/step-cli:0.26.0@sha256:7e21dd9f07cdf7993e99905ee331b7bcc25f46ac5c4b3a7efb586bb8f786c122","Warn: containerImage not pinned by hash: examples/hello-mtls/curl/Dockerfile.client:1: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: containerImage not pinned by hash: examples/hello-mtls/envoy/Dockerfile.server:1","Warn: containerImage not pinned by hash: examples/hello-mtls/go-grpc/client/Dockerfile.client:2","Warn: containerImage not pinned by hash: examples/hello-mtls/go-grpc/client/Dockerfile.client:14: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: containerImage not pinned by hash: examples/hello-mtls/go-grpc/server/Dockerfile.server:2","Warn: containerImage not pinned by hash: examples/hello-mtls/go-grpc/server/Dockerfile.server:13: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: containerImage not pinned by hash: examples/hello-mtls/go/client/Dockerfile.client:2","Warn: containerImage not pinned by hash: examples/hello-mtls/go/client/Dockerfile.client:8: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: containerImage not pinned by hash: examples/hello-mtls/go/server/Dockerfile.server:2","Warn: containerImage not pinned by hash: examples/hello-mtls/go/server/Dockerfile.server:8: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: containerImage not pinned by hash: examples/hello-mtls/nginx/Dockerfile.server:1: pin your Docker image by updating nginx:alpine to nginx:alpine@sha256:2459838ed006e699c252db374550c91490068bbf3b35fa8b9d29bfe0e31b8b95","Warn: containerImage not pinned by hash: examples/hello-mtls/node/Dockerfile.client:1: pin your Docker image by updating node:lts-alpine to node:lts-alpine@sha256:1b2479dd35a99687d6638f5976fd235e26c5b37e8122f786fcd5fe231d63de5b","Warn: containerImage not pinned by hash: examples/hello-mtls/node/Dockerfile.server:1: pin your Docker image by updating node:lts-alpine to node:lts-alpine@sha256:1b2479dd35a99687d6638f5976fd235e26c5b37e8122f786fcd5fe231d63de5b","Warn: containerImage not pinned by hash: examples/hello-mtls/py-gunicorn/Dockerfile.client:1: pin your Docker image by updating python:alpine to python:alpine@sha256:a70b35b575e33d951e3f9d3fe94163ef0fd338c22552bc587a1b098a87ed6184","Warn: containerImage not pinned by hash: examples/hello-mtls/py-gunicorn/Dockerfile.server:1: pin your Docker image by updating python:alpine to python:alpine@sha256:a70b35b575e33d951e3f9d3fe94163ef0fd338c22552bc587a1b098a87ed6184","Warn: containerImage not pinned by hash: init/Dockerfile:1: pin your Docker image by updating smallstep/step-cli:0.26.0 to smallstep/step-cli:0.26.0@sha256:7e21dd9f07cdf7993e99905ee331b7bcc25f46ac5c4b3a7efb586bb8f786c122","Warn: containerImage not pinned by hash: renewer/Dockerfile:1: pin your Docker image by updating smallstep/step-cli:0.26.0 to smallstep/step-cli:0.26.0@sha256:7e21dd9f07cdf7993e99905ee331b7bcc25f46ac5c4b3a7efb586bb8f786c122","Warn: pipCommand not pinned by hash: examples/hello-mtls/envoy/Dockerfile.server:17","Warn: pipCommand not pinned by hash: examples/hello-mtls/py-gunicorn/Dockerfile.client:7","Warn: pipCommand not pinned by hash: examples/hello-mtls/py-gunicorn/Dockerfile.server:11","Info:   1 out of  12 third-party GitHubAction dependencies pinned","Info:   0 out of   3 pipCommand dependencies pinned","Info:   2 out of   2 goCommand dependencies pinned","Info:   0 out of  20 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}}]},"last_synced_at":"2025-08-23T18:06:02.964Z","repository_id":38010741,"created_at":"2025-08-23T18:06:02.964Z","updated_at":"2025-08-23T18:06:02.964Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"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":[],"created_at":"2024-08-04T08:00:54.012Z","updated_at":"2026-04-01T18:19:28.906Z","avatar_url":"https://github.com/smallstep.png","language":"Go","funding_links":[],"categories":["others","Go (531)","Go"],"sub_categories":[],"readme":"![Autocert architecture diagram](https://raw.githubusercontent.com/smallstep/autocert/master/autocert-logo.png)\n\n# Autocert\n[![GitHub release](https://img.shields.io/github/release/smallstep/autocert.svg)](https://github.com/smallstep/autocert/releases)\n[![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/autocert)](https://goreportcard.com/report/github.com/smallstep/autocert)\n\n[![GitHub stars](https://img.shields.io/github/stars/smallstep/autocert.svg?style=social)](https://github.com/smallstep/autocert/stargazers)\n[![Twitter followers](https://img.shields.io/twitter/follow/smallsteplabs.svg?label=Follow\u0026style=social)](https://twitter.com/intent/follow?screen_name=smallsteplabs)\n[![Join the Discord](https://img.shields.io/badge/discord--green?logo=discord\u0026style=social)](https://bit.ly/step-discord)\n\n**Autocert** is a Kubernetes add-on that automatically injects TLS/HTTPS certificates into your containers, so they can communicate with each other securely.\n\nTo get a certificate **simply annotate your pods** with a name. An X.509 (TLS/HTTPS) certificate is automatically created and mounted at `/var/run/autocert.step.sm/` along with a corresponding private key and root certificate (everything you need for [mTLS](#motivation)).\n\nThe certificates are signed by an internal [step-ca](https://github.com/smallstep/certificates/) Certificate Authority (CA) or by [Certificate Manager](https://smallstep.com/certificate-manager/) (see [Tutorial \u0026 Demo](#tutorial--demo)).\n\n\u003e By the way, we also have a [cert-manager](https://cert-manager.io/) Certificate Issuer called [step-issuer](https://github.com/smallstep/step-issuer) that works directly with either your [step-ca](https://github.com/smallstep/certificates/) server or [our cloud CA product](https://smallstep.com/certificate-manager/). While Autocert volume mounts certificates and keys directly into Pods, step-issuer makes them available via Secrets.\n\nWe ❤️  feedback, [bugs](https://github.com/smallstep/autocert/issues/new?template=autocert_bug.md), and [enhancement suggestions](https://github.com/smallstep/autocert/issues/new?template=autocert_enhancement.md). We also have an #autocert channel [on our Discord](https://bit.ly/step-discord).\n\n![Autocert demo gif](https://raw.githubusercontent.com/smallstep/autocert/master/demo.gif)\n\n## Motivation\n\n`Autocert` exists to **make it easy to use mTLS** ([mutual TLS](examples/hello-mtls/README.md#mutual-tls)) to **improve security** within a cluster and to **secure communication into, out of, and between kubernetes clusters**.\n\nTLS (and HTTPS, which is HTTP over TLS) provides _authenticated encryption_: an _identity dialtone_ and _end-to-end encryption_ for your workloads. It **makes workloads identity-aware**, improving observability and enabling granular access control. Perhaps most compelling, mTLS lets you securely communicate with workloads running anywhere, not just inside kubernetes.\n\n![Connect with mTLS diagram](https://raw.githubusercontent.com/smallstep/autocert/master/connect-with-mtls.png)\n\nUnlike VPNs \u0026 SDNs, deploying and scaling mTLS is pretty easy. You're (hopefully) already using TLS, and your existing tools and standard libraries will provide most of what you need.\n\nThere's just one problem: **you need certificates issued by your own certificate authority (CA)**. Building and operating a CA, issuing certificates, and making sure they're renewed before they expire is tricky. `Autocert` does all of this for you.\n\n## Features\n\nFirst and foremost, `autocert` is easy. You can **get started in minutes**.\n\n`Autocert` runs [`step-ca`](https://github.com/smallstep/certificates) to internally generate keys and issue certificates. This process is secure and automatic, all you have to do is [install autocert](#install) and [annotate your pods](#enable-autocert-per-namespace).\n\nFeatures include:\n\n * A fully featured private CA for workloads running on kubernetes and elsewhere\n * [RFC5280](https://tools.ietf.org/html/rfc5280) and [CA/Browser Forum](https://cabforum.org/baseline-requirements-documents/) compliant certificates that work for TLS\n * Namespaced installation into the `step` namespace so it's easy to lock down your CA\n * Short-lived certificates with fully automated enrollment and renewal\n * Private keys are never transmitted across the network and aren't stored in `etcd`\n\n Because `autocert` is built on [`step-ca`](https://github.com/smallstep/certificates) you can easily [extend access](#connecting-from-outside-the-cluster) to developers, endpoints, and workloads running outside your cluster, too.\n\n## Tutorial \u0026 Demo\n\n\u003ca href=\"https://www.youtube.com/watch?v=NhHkfvSuKiM\"\u003e\u003cimg width=\"800\" alt=\"smallstep-cm-autocert-demo-keyframe\" src=\"https://user-images.githubusercontent.com/50809/179625695-347bdb75-0376-443d-be21-ce30e55cacee.png\"\u003e\u003c/a\u003e\n\nIn [this tutorial video](https://www.youtube.com/watch?v=NhHkfvSuKiM), Smallstep Software Engineer Andrew Reed shows how to use autocert alongside Smallstep [Certificate Manager](https://smallstep.com/certificate-manager/) hosted CA.\n\n## Installation\n\n### Prerequisites\n\nAll you need to get started is [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl) and a cluster running kubernetes with [admission webhooks](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) enabled:\n\n```bash\n$ kubectl version\nClient Version: v1.26.1\nKustomize Version: v4.5.7\nServer Version: v1.25.3\n$ kubectl api-versions | grep \"admissionregistration.k8s.io/v1\"\nadmissionregistration.k8s.io/v1\n```\n\n### Install via `kubectl`\n\nTo install `autocert` run:\n\n```bash\nkubectl run autocert-init -it --rm --image cr.smallstep.com/smallstep/autocert-init --restart Never\n```\n\n💥 installation complete.\n\n\u003e You might want to [check out what this command does](init/autocert.sh) before running it. You can also [install `autocert` manually](INSTALL.md#manual-install) if that's your style.\n\n#### Install via Helm\n\nAutocert can also be installed using the [Helm](https://helm.sh) package\nmanager, to install the repository and `autocert` run:\n\n```bash\nhelm repo add smallstep https://smallstep.github.io/helm-charts/\nhelm repo update\nhelm install smallstep/autocert\n```\n\nYou can see all the configuration options at https://hub.helm.sh/charts/smallstep/autocert.\n\n## Usage\n\nUsing `autocert` is also easy:\n\n * Enable `autocert` for a namespace by labelling it with `autocert.step.sm=enabled`, then\n * Inject certificates into containers by annotating pods with `autocert.step.sm/name: \u003cname\u003e`\n\n### Enable autocert (per namespace)\n\nTo enable `autocert` for a namespace it must be labelled `autocert.step.sm=enabled`.\n\nTo label the `default` namespace run:\n\n```bash\nkubectl label namespace default autocert.step.sm=enabled\n```\n\nTo check which namespaces have `autocert` enabled run:\n\n```bash\n$ kubectl get namespace -L autocert.step.sm\nNAME          STATUS   AGE   AUTOCERT.STEP.SM\ndefault       Active   59m   enabled\n...\n```\n\n### Annotate pods to get certificates\n\nTo get a certificate you need to tell `autocert` your workload's name using the\n`autocert.step.sm/name` annotation (this name will appear as the X.509 common\nname and SAN).\n\nIt's also possible to define the duration of the certificate using the\nannotation `autocert.step.sm/duration`, a duration is a sequence of decimal\nnumbers, each with optional fraction and a unit suffix, such as \"300ms\", \"1.5h\"\nor \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\". Take\ninto account that the container will crash if the duration is not between the\nlimits defined by the used provisioner, the defaults are 5m and 24h.\n\nBy default the certificate, key and root will be owned by root and world-readable (0644).\nUse the `autocert.step.sm/owner` and `autocert.step.sm/mode` annotations to set the owner and permissions of the files.\nThe owner annotation requires user and group IDs rather than names because the images used by the containers that create and renew the certificates do not have the same user list as the main application containers.\n\n\nLet's deploy a [simple mTLS server](examples/hello-mtls/go/server/server.go)\nnamed `hello-mtls.default.svc.cluster.local`:\n\n```yaml\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: apps/v1\nkind: Deployment\nmetadata: {name: hello-mtls, labels: {app: hello-mtls}}\nspec:\n  replicas: 1\n  selector: {matchLabels: {app: hello-mtls}}\n  template:\n    metadata:\n      annotations:\n        # AUTOCERT ANNOTATION HERE -v ###############################\n        autocert.step.sm/name: hello-mtls.default.svc.cluster.local #\n        # AUTOCERT ANNOTATION HERE -^ ###############################\n      labels: {app: hello-mtls}\n    spec:\n      containers:\n      - name: hello-mtls\n        image: smallstep/hello-mtls-server-go:latest\nEOF\n```\n\nIn our new container we should find a certificate, private key, and root\ncertificate mounted at `/var/run/autocert.step.sm`:\n\n```bash\n$ export HELLO_MTLS=$(kubectl get pods -l app=hello-mtls -o jsonpath='{$.items[0].metadata.name}')\n$ kubectl exec -it $HELLO_MTLS -c hello-mtls -- ls /var/run/autocert.step.sm\nroot.crt  site.crt  site.key\n```\n\nWe're done. Our container has a certificate, issued by our CA, which `autocert`\nwill automatically renew.\n\nNow let's deploy another server with a `autocert.step.sm/duration`, `autocert.step.sm/owner` and `autocert.step.sm/mode`:\n\n```yaml\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: apps/v1\nkind: Deployment\nmetadata: {name: hello-mtls-1h, labels: {app: hello-mtls-1h}}\nspec:\n  replicas: 1\n  selector: {matchLabels: {app: hello-mtls-1h}}\n  template:\n    metadata:\n      annotations:\n        autocert.step.sm/name: hello-mtls-1h.default.svc.cluster.local\n        autocert.step.sm/duration: 1h\n        autocert.step.sm/owner: \"999:999\"\n        autocert.step.sm/mode: \"0600\"\n      labels: {app: hello-mtls-1h}\n    spec:\n      containers:\n      - name: hello-mtls\n        image: smallstep/hello-mtls-server-go:latest\nEOF\n```\n\nThe container will have the certificates and key owned by user/group 999 with permission to read/write restricted to the owner, and the certificate duration will be valid for one hour and will be autorenewed:\n\n```bash\n$ export HELLO_MTLS_1H=$(kubectl get pods -l app=hello-mtls-1h -o jsonpath='{$.items[0].metadata.name}')\n$ kubectl exec -it $HELLO_MTLS_1H -c hello-mtls -- ls -ln /var/run/autocert.step.sm\n-rw------- 1 999 999  623 Jun  6 21:17 root.crt\n-rw------- 1 999 999 1470 Jun  6 21:37 site.crt\n-rw------- 1 999 999  227 Jun  6 21:17 site.key\n$ kubectl exec -it $HELLO_MTLS_1H -c hello-mtls -- cat /var/run/autocert.step.sm/site.crt | step certificate inspect --short -\nX.509v3 TLS Certificate (ECDSA P-256) [Serial: 3182...1140]\n  Subject:     hello-mtls-1h.default.svc.cluster.local\n  Issuer:      Autocert Intermediate CA\n  Provisioner: autocert [ID: A1lX...ty1Q]\n  Valid from:  2020-04-30T01:58:17Z\n          to:  2020-04-30T02:58:17Z\n```\n\nDurations are specially useful if the `step-ca` provisioner is configured with a\nmaximum duration larger than the default one, it can be used by services that\ncannot handle the reload of the certificates in a graceful way.\n\n✅ Certificates.\n\n## Hello mTLS\n\nIt's easy to deploy certificates using `autocert`, but it's up to you to use them correctly. To get you started, [`hello-mtls`](examples/hello-mtls) demonstrates the right way to use mTLS with various tools and languages (contributions welcome :). If you're a bit fuzzy on how mTLS works, [the `hello-mtls` README](examples/hello-mtls/README.md) is a great place to start.\n\nTo finish out this tutorial let's keep things simple and try `curl`ing the server we just deployed from inside and outside the cluster.\n\n### Connecting from inside the cluster\n\nFirst, let's expose our workload to the rest of the cluster using a service:\n\n```\nkubectl expose deployment hello-mtls --port 443\n```\n\nNow let's deploy a client, with its own certificate, that [`curl`s our server in a loop](examples/hello-mtls/curl/client.sh):\n\n```yaml\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: apps/v1\nkind: Deployment\nmetadata: {name: hello-mtls-client, labels: {app: hello-mtls-client}}\nspec:\n  replicas: 1\n  selector: {matchLabels: {app: hello-mtls-client}}\n  template:\n    metadata:\n      annotations:\n        # AUTOCERT ANNOTATION HERE -v ######################################\n        autocert.step.sm/name: hello-mtls-client.default.pod.cluster.local #\n        # AUTOCERT ANNOTATION HERE -^ ######################################\n      labels: {app: hello-mtls-client}\n    spec:\n      containers:\n      - name: hello-mtls-client\n        image: smallstep/hello-mtls-client-curl:latest\n        env: [{name: HELLO_MTLS_URL, value: https://hello-mtls.default.svc.cluster.local}]\nEOF\n```\n\n\u003e Note that **the authority portion of the URL** (the `HELLO_MTLS_URL` env var) **matches the name of the server we're connecting to** (both are `hello-mtls.default.svc.cluster.local`). That's required for standard HTTPS and can sometimes require some DNS trickery.\n\nOnce deployed we should start seeing the client log responses from the server [saying hello](examples/hello-mtls/go/server/server.go#L71-L72):\n\n```\n$ export HELLO_MTLS_CLIENT=$(kubectl get pods -l app=hello-mtls-client -o jsonpath='{$.items[0].metadata.name}')\n$ kubectl logs $HELLO_MTLS_CLIENT -c hello-mtls-client\nThu Feb  7 23:35:23 UTC 2019: Hello, hello-mtls-client.default.pod.cluster.local!\nThu Feb  7 23:35:28 UTC 2019: Hello, hello-mtls-client.default.pod.cluster.local!\n```\n\nFor kicks, let's `exec` into this pod and try `curl`ing ourselves:\n\n```\n$ kubectl exec $HELLO_MTLS_CLIENT -c hello-mtls-client -- curl -sS \\\n       --cacert /var/run/autocert.step.sm/root.crt \\\n       --cert /var/run/autocert.step.sm/site.crt \\\n       --key /var/run/autocert.step.sm/site.key \\\n       https://hello-mtls.default.svc.cluster.local\nHello, hello-mtls-client.default.pod.cluster.local!\n```\n\n✅ mTLS inside cluster.\n\n### Connecting from outside the cluster\n\nConnecting from outside the cluster is a bit more complicated. We need to handle DNS and obtain a certificate ourselves. These tasks were handled automatically inside the cluster by kubernetes and `autocert`, respectively.\n\nThat said, because our server uses mTLS **only clients that have a certificate issued by our certificate authority will be allowed to connect**. That means it can be safely and easily exposed directly to the public internet using a [LoadBalancer service type](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer):\n\n```\nkubectl expose deployment hello-mtls --name=hello-mtls-lb --port=443 --type=LoadBalancer\n```\n\nTo connect we need a certificate. There are a [couple](RUNBOOK.md#federation) [different](RUNBOOK.md#multiple-intermediates) [ways](RUNBOOK.md#exposing-the-ca) to get one, but for simplicity we'll just forward a port.\n\n```\nkubectl -n step port-forward $(kubectl -n step get pods -l app=ca -o jsonpath={$.items[0].metadata.name}) 4443:4443\n```\n\nIn another window we'll use `step` to grab the root certificate, generate a key pair, and get a certificate.\n\n\u003e To follow along you'll need to [`install step`](https://github.com/smallstep/cli#installing) if you haven't already. You'll also need your admin password and CA fingerprint, which were output during installation (see [here](RUNBOOK.md#recover-admin-and-ca-password) and [here](RUNBOOK.md#recompute-root-certificate-fingerprint) if you already lost them :).\n\n```bash\n$ export CA_POD=$(kubectl -n step get pods -l app=ca -o jsonpath='{$.items[0].metadata.name}')\n$ step ca root root.crt --ca-url https://127.0.0.1:4443 --fingerprint \u003cfingerprint\u003e\n$ step ca certificate mike mike.crt mike.key --ca-url https://127.0.0.1:4443 --root root.crt\n✔ Key ID: H4vH5VfvaMro0yrk-UIkkeCoPFqEfjF6vg0GHFdhVyM (admin)\n✔ Please enter the password to decrypt the provisioner key: 0QOC9xcq56R1aEyLHPzBqN18Z3WfGZ01\n✔ CA: https://127.0.0.1:4443/1.0/sign\n✔ Certificate: mike.crt\n✔ Private Key: mike.key\n```\n\nNow we can simply `curl` the service:\n\n\u003e If you're using minikube or docker for mac the load balancer's \"IP\" might be `localhost`, which won't work. In that case, simply `export HELLO_MTLS_IP=127.0.0.1` and try again.\n\n```\n$ export HELLO_MTLS_IP=$(kubectl get svc hello-mtls-lb -ojsonpath={$.status.loadBalancer.ingress[0].ip})\n$ curl --resolve hello-mtls.default.svc.cluster.local:443:$HELLO_MTLS_IP \\\n       --cacert root.crt \\\n       --cert mike.crt \\\n       --key mike.key \\\n       https://hello-mtls.default.svc.cluster.local\nHello, mike!\n```\n\n\u003e Note that we're using `--resolve` to tell `curl` to override DNS and resolve the name in our workload's certificate to its public IP address. In a real production infrastructure you could configure DNS manually, or you could propagate DNS to workloads outside kubernetes using something like [ExternalDNS](https://github.com/kubernetes-incubator/external-dns).\n\n✅ mTLS outside cluster.\n\n### Cleanup \u0026 uninstall\n\nTo clean up after running through the tutorial remove the `hello-mtls` and `hello-mtls-client` deployments and services:\n\n```\nkubectl delete deployment hello-mtls\nkubectl delete deployment hello-mtls-client\nkubectl delete service hello-mtls\nkubectl delete service hello-mtls-lb\n```\n\nSee the runbook for instructions on [uninstalling `autocert`](RUNBOOK.md#uninstalling).\n\n## How it works\n\n### Architecture\n\n`Autocert` is an [admission webhook](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) that intercepts and patches pod creation requests with [some YAML](install/02-autocert.yaml#L26-L44) to inject an [init container](bootstrapper/) and [sidecar](renewer/) that handle obtaining and renewing certificates, respectively.\n\n![Autocert architecture diagram](https://raw.githubusercontent.com/smallstep/autocert/master/autocert-arch.png)\n\n### Enrollment \u0026 renewal\n\nIt integrates with [`step certificates`](https://github.com/smallstep/certificates) and uses the [one-time token bootstrap protocol](https://smallstep.com/blog/step-certificates.html#automated-certificate-management) from that project to mutually authenticate a new pod with your certificate authority, and obtain a certificate.\n\n![Autocert bootstrap protocol diagram](https://raw.githubusercontent.com/smallstep/autocert/master/autocert-bootstrap.png)\n\nTokens are [generated by the admission webhook](controller/provisioner.go#L46-L72) and [transmitted to the injected init container via a kubernetes secret](controller/main.go#L91-L125). The init container [uses the one-time token](bootstrapper/bootstrapper.sh) to obtain a certificate. A sidecar is also installed to [renew certificates](renewer/Dockerfile#L8) before they expire. Renewal simply uses mTLS with the CA.\n\n## FAQs\n\n### Wait, so any pod can get a certificate with any identity? How is that secure?\n\n 1. Don't give people `kubectl` access to your production clusters\n 2. Use a deploy pipeline based on `git` artifacts\n 3. Enforce code review on those `git` artifacts\n\n If that doesn't work for you, or if you have a better idea, we'd love to hear! Please [open an issue](https://github.com/smallstep/autocert/issues/new?template=autocert_enhancement.md)!\n\n ### Why do I have to tell you the name to put in a certificate? Why can't you automatically bind service names?\n\nMostly because monitoring the API server to figure out which services are associated with which workloads is complicated and somewhat magical. And it might not be what you want.\n\nThat said, we're not totally opposed to this idea. If anyone has strong feels and a good design please [open an issue](https://github.com/smallstep/autocert/issues/new?template=autocert_enhancement.md).\n\n### Doesn't Kubernetes already ship with a CA?\n\nKubernetes needs [several certificates](https://jvns.ca/blog/2017/08/05/how-kubernetes-certificates-work/) for different sorts of control plane communication.\nIt ships with a very limited CA\nand integration points that allow you to use an alternative CA.\n\nThe built-in Kuberenetes CA is limited to signing certificates for kubeconfigs and kubelets.\nSpecifically, the [controller-manager will sign CSRs in some cases](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signer-control-plane).\n\nSee our blog [Automating TLS in Kubernetes The Hard Way](https://smallstep.com/blog/kubernetes-the-secure-way/) to learn a lot more.\n\nWhile you _could_ use the Kubernetes CA for service-to-service data plane and ingress certificates,\nwe don't recommend it.\nHaving two CAs will give you a crisp cryptographic boundary.\n\n### What permissions does `autocert` require in my cluster and why?\n\n`Autocert` needs permission to create and delete secrets cluster-wide. You can [check out our RBAC config here](install/03-rbac.yaml). These permissions are needed in order to transmit one-time tokens to workloads using secrets, and to clean up afterwards. We'd love to scope these permissions down further. If anyone has any ideas please [open an issue](https://github.com/smallstep/autocert/issues/new?template=autocert_enhancement.md).\n\n#### Why does `autocert` create secrets?\n\nThe `autocert` admission webhook needs to securely transmit one-time bootstrap tokens to containers. This could be accomplished without using secrets. The webhook returns a [JSONPatch](https://tools.ietf.org/html/rfc6902) response that's applied to the pod spec. This response could patch the literal token value into our init container's environment.\n\nUnfortunately, the kubernetes API server does not authenticate itself to admission webhooks by default, and configuring it to do so [requires passing a custom config file](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers) at apiserver startup. This isn't an option for everyone (e.g., on GKE) so we opted not to rely on it.\n\nSince our webhook can't authenticate callers, including bootstrap tokens in patch responses would be dangerous. By using secrets an attacker can still trick `autocert` into generating superflous bootstrap tokens, but they'd also need read access to cluster secrets to do anything with them.\n\nHopefully this story will improve with time.\n\n### Why not use kubernetes service accounts instead of bootstrap tokens?\n\nGreat idea! This should be pretty easy to add using the [TokenRequest API](https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/).\n\n### Can I lengthen the duration of the bootstrap tokens?\n\nIf you're facing deployment times longer than five minutes, use the annotation `autocert.step.sm/init-first: \"true\"`, which will force the bootstrapper to run before any other initContainer. As long as the CA is available, you will get a certificate valid for 24h that should be enough for initializing the rest of the deployment. After the bootstrapper, it will run the rest of the initContainers that can wait for the dependencies to be ready. See [smallstep/autocert#108](https://github.com/smallstep/autocert/issues/108) for more details.\n\n### Too. many. containers. Why do you need to install an init container _and_ a sidecar?\n\nWe don't. It's just easier for you. Your containers can generate key pairs, exchange them for certificates, and manage renewals themselves. This is pretty easy if you [install `step`](https://github.com/smallstep/cli#installing) in your containers, or integrate with our [golang SDK](https://godoc.org/github.com/smallstep/certificates/ca). To support this we'd need to add the option to inject a bootstrap token without injecting these containers.\n\nThat said, the init container and sidecar are both super lightweight.\n\n### Why are keys and certificates managed via volume mounts? Why not use a Secret or some custom resource?\n\nBecause, by default, kubernetes Secrets are stored in plaintext in `etcd` and might even be transmitted unencrypted across the network. Even if Secrets were properly encrypted, transmitting a private key across the network violates PKI best practices. Key pairs should always be generated where they're used, and private keys should never be known by anyone but their owners.\n\nThat said, there are use cases where a certificate mounted in a Secret resource is desirable (e.g., for use with a kubernetes `Ingress`). For that, we recommend [`step-issuer`](https://github.com/smallstep/step-issuer).\n\n(Add a 👍 to smallstep/autocert#48 I'd like `autocert` to expose Secrets in the future.)\n\n### How is this different than [`cert-manager`](https://github.com/jetstack/cert-manager)\n\n`Cert-manager` is a great project, but it's design is focused on managing Web PKI certificates issued by [Let's Encrypt's](https://letsencrypt.org/) public certificate authority. These certificates are useful for TLS ingress from web browsers. `Autocert` is purpose-built to manage certificates issued by your own private CA to support the use of mTLS for service-to-service communication.\n\n### What sorts of keys are issued and how often are certificates rotated?\n\n`Autocert` builds on `step certificates` which issues ECDSA certificates using the P256 curve with ECDSA-SHA256 signatures by default. If this is all Greek to you, rest assured these are safe, sane, and modern defaults that are suitable for the vast majority of environments.\n\n### What crypto library is under the hood?\n\nhttps://golang.org/pkg/crypto/\n\n## Building\n\nThis project is based on four container images:\n- `autocert-controller` (the admission webhook)\n- `autocert-bootstrapper` (the init container that generates a key pair and exchanges a bootstrap token for a certificate)\n- `autocert-renewer` (the sidecar that renews certificates)\n- `autocert-init` (the install script)\n\nThey use [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) so all you need in order to build them is `docker`.\n\nTo build all of the images, run:\n\n```\ndocker build -t smallstep/autocert-controller:latest -f controller/Dockerfile .\ndocker build -t smallstep/autocert-bootstrapper:latest -f bootstrapper/Dockerfile .\ndocker build -t smallstep/autocert-renewer:latest -f renewer/Dockerfile .\ndocker build -t smallstep/autocert-init:latest -f init/Dockerfile .\n```\n\nIf you build your own containers you'll probably need to [install manually](INSTALL.md). You'll also need to adjust which images are deployed in the [deployment yaml](install/02-autocert.yaml).\n\n## Contributing\n\nIf you have improvements to `autocert`, send us your pull requests! For those just getting started, GitHub has a [howto](https://help.github.com/articles/about-pull-requests/). A team member will review your pull requests, provide feedback, and merge your changes. In order to accept contributions we do need you to [sign our contributor license agreement](https://cla-assistant.io/smallstep/autocert).\n\nIf you want to contribute but you're not sure where to start, take a look at the [issues with the \"good first issue\" label](https://github.com/smallstep/autocert/issues?q=is%3Aopen+label%3A%22good+first+issue%22+label%3Aarea%2Fautocert). These are issues that we believe are particularly well suited for outside contributions, often because we probably won't get to them right now. If you decide to start on an issue, leave a comment so that other people know that you're working on it. If you want to help out, but not alone, use the issue comment thread to coordinate.\n\nIf you've identified a bug or have ideas for improving `autocert` that you don't have time to implement, we'd love to hear about them. Please open an issue to [report a bug](https://github.com/smallstep/autocert/issues/new?template=autocert_bug.md) or [suggest an enhancement](https://github.com/smallstep/autocert/issues/new?template=autocert_enhancement.md)!\n\n## Further Reading\n\n * We tweet [@smallsteplabs](https://twitter.com/smallsteplabs)\n * Read [our blog](https://smallstep.com/blog)\n * Check out the [runbook](RUNBOOK.md)\n * Check out [`step` CLI](https://github.com/smallstep/cli)\n\n## License\n\nCopyright 2023 Smallstep Labs\n\nLicensed under [the Apache License, Version 2.0](https://github.com/smallstep/autocert/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmallstep%2Fautocert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmallstep%2Fautocert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmallstep%2Fautocert/lists"}