{"id":16885136,"url":"https://github.com/ericchiang/etcd-security-guide","last_synced_at":"2025-10-27T19:33:50.972Z","repository":{"id":145909907,"uuid":"130924766","full_name":"ericchiang/etcd-security-guide","owner":"ericchiang","description":"A guide for deploying etcd clusters securely using TLS","archived":false,"fork":false,"pushed_at":"2018-04-26T23:16:36.000Z","size":11,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T23:38:44.640Z","etag":null,"topics":["etcd","tls"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ericchiang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-04-24T23:28:32.000Z","updated_at":"2025-02-08T13:31:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"5de8ab5c-e20f-4f33-b1f3-e9070bd6d90d","html_url":"https://github.com/ericchiang/etcd-security-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ericchiang/etcd-security-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericchiang%2Fetcd-security-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericchiang%2Fetcd-security-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericchiang%2Fetcd-security-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericchiang%2Fetcd-security-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ericchiang","download_url":"https://codeload.github.com/ericchiang/etcd-security-guide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericchiang%2Fetcd-security-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001978,"owners_count":26083259,"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-10-09T02:00:07.460Z","response_time":59,"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":["etcd","tls"],"created_at":"2024-10-13T16:33:35.530Z","updated_at":"2025-10-09T20:37:02.151Z","avatar_url":"https://github.com/ericchiang.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# etcd Security Guide\n\nA guide for deploying etcd clusters securely using TLS. \n\netcd's default options, and many tutorials, don't use TLS or any form of authentication. As a result [many insecure clusters find their way into the wild][etcd-security-blog-post].\n\nThis document provides examples of how to provision TLS assets for an etcd cluster, and acts as a reference for which flags to enable to correctly secure client and peer traffic. At some point this content will be contributed to the [upstream etcd security guide][etcd-security].\n\nThis document requires the [latest release of etcd][etcd-releases] and CloudFlare's [cfssl and cfssljson][cfssl-install] tools to run the examples.\n\n## Generating TLS assets\n\netcd instances require 2 sets of TLS certificates: one cert to serve client requests and a second for the peer endpoint used for communication between members. The peer cert doubles as a serving cert and client cert for traffic between the peers.\n\nFor this demo add the following entries to `/etc/hosts`:\n\n```\n127.0.0.1   etcd-1.local etcd-2.local etcd-3.local\n```\n\nFirst, initialize the `cfssl` profiles and config files. These control the common name of the generate certificates, the allowed usages, and expiry:\n\n```bash\nmkdir -p tls/profiles\necho '{\n  \"signing\": {\n    \"default\": {\n      \"expiry\": \"43800h\"\n    },\n    \"profiles\": {\n      \"server\": {\n        \"expiry\": \"43800h\",\n        \"usages\": [\"signing\", \"key encipherment\", \"server auth\"]\n      },\n      \"client\": {\n        \"expiry\": \"43800h\",\n        \"usages\": [\"signing\", \"key encipherment\", \"client auth\"]\n      },\n      \"peer\": {\n        \"expiry\": \"43800h\",\n        \"usages\": [\"signing\", \"key encipherment\", \"server auth\", \"client auth\"]\n      }\n    }\n  }\n}' \u003e tls/profiles/config.json\necho '{\"CN\":\"etcd-ca\",\"key\":{\"algo\":\"ecdsa\",\"size\":256}}' \u003e tls/profiles/ca.json\necho '{\"CN\":\"root\",\"key\":{\"algo\":\"ecdsa\",\"size\":256}}' \u003e tls/profiles/client.json\necho '{\"CN\":\"etcd-member\",\"key\":{\"algo\":\"ecdsa\",\"size\":256}}' \u003e tls/profiles/peer.json\necho '{\"CN\":\"etcd-server\",\"key\":{\"algo\":\"ecdsa\",\"size\":256}}' \u003e tls/profiles/server.json\n```\n\nNext, generate a certifiate authority, a client cert, and serving and peer certs for each member:\n\n```bash\nmkdir -p tls/assets\n\ncfssl gencert -initca tls/profiles/ca.json | cfssljson -bare tls/assets/ca\n\n# Generate a client cert\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=client \\\n    tls/profiles/client.json | cfssljson -bare tls/assets/client\n\n# Generate a serving and peer certs for each etcd member\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=peer -hostname=\"etcd-1.local\" \\\n    tls/profiles/peer.json | cfssljson -bare tls/assets/member-1-peer\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=server -hostname=\"etcd-1.local\" \\\n    tls/profiles/server.json | cfssljson -bare tls/assets/member-1-server\n\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=peer -hostname=\"etcd-2.local\" \\\n    tls/profiles/peer.json | cfssljson -bare tls/assets/member-2-peer\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=server -hostname=\"etcd-2.local\" \\\n    tls/profiles/server.json | cfssljson -bare tls/assets/member-2-server\n\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=peer -hostname=\"etcd-3.local\" \\\n    tls/profiles/peer.json | cfssljson -bare tls/assets/member-3-peer\ncfssl gencert -ca=tls/assets/ca.pem -ca-key=tls/assets/ca-key.pem \\\n    -config=tls/profiles/config.json -profile=server -hostname=\"etcd-3.local\" \\\n    tls/profiles/server.json | cfssljson -bare tls/assets/member-3-server\n\n# Remove generated CSRs\nrm tls/assets/*.csr\n```\n\nThese commands will create the following directory structure:\n\n```terminal\n$ tree tls/\ntls/\n├── assets\n│   ├── ca-key.pem\n│   ├── ca.pem\n│   ├── member-1-peer-key.pem\n│   ├── member-1-peer.pem\n│   ├── member-1-server-key.pem\n│   ├── member-1-server.pem\n│   ├── member-2-peer-key.pem\n│   ├── member-2-peer.pem\n│   ├── member-2-server-key.pem\n│   ├── member-2-server.pem\n│   ├── member-3-peer-key.pem\n│   ├── member-3-peer.pem\n│   ├── member-3-server-key.pem\n│   └── member-3-server.pem\n└── profiles\n    ├── ca.json\n    ├── client.json\n    ├── config.json\n    ├── peer.json\n    └── server.json\n\n2 directories, 19 files\n```\n\n## Running a secured cluster\n\nTo run etcd using HTTPS provide endpoints that use a `https://` scheme, specifiy cert and key flags, and enable client auth. The following flags are used to load TLS assets for the client endpoint and enforce TLS client auth:\n\n```\n--cert-file=tls/assets/member-1-server.pem\n--key-file=tls/assets/member-1-server-key.pem\n--client-cert-auth=true\n--trusted-ca-file=tls/assets/ca.pem\n```\n\nThe following flags are used to load TLS assets for the peer endpoint (reminder that peer certs double as serving and client certs) and restrict TLS client auth to other etcd members:\n\n```\n--peer-cert-file=tls/assets/member-1-peer.pem\n--peer-key-file=tls/assets/member-1-peer-key.pem\n--peer-cert-allowed-cn=etcd-member\n--peer-client-cert-auth=true\n--peer-trusted-ca-file=tls/assets/ca.pem\n```\n\nThe [`run-cluster.sh`](./scripts/run-cluster.sh) script runs a 3 member etcd cluster locally. It configures each to use the generated TLS assets and enables the correct set of flags to enforce authentication:\n\n```\n$ ./scripts/run-cluster.sh\netcd 1 running: PID 25622\netcd 2 running: PID 25623\netcd 3 running: PID 25624\n```\n\nMembers write their logs to the `logs/` directory. Use `tail` to ensure the cluster came up correctly and formed quorum.\n\n```\n$ tail -f logs/*                  \n```\n\nConfigure `etcdctl` with the admin client certificate:\n\n```\nexport ETCDCTL_API=3\nexport ETCDCTL_ENDPOINTS='https://etcd-1.local:12379,https://etcd-2.local:22379,https://etcd-3.local:32379'\nexport ETCDCTL_CACERT=$PWD/tls/assets/ca.pem\nexport ETCDCTL_CERT=$PWD/tls/assets/client.pem\nexport ETCDCTL_KEY=$PWD/tls/assets/client-key.pem\n```\n\nIf the scripts work `etcdctl` should be able to interact with the cluster:\n\n```\n$ etcdctl member list                                                \n1dbd05ce059524ef, started, infra3, https://etcd-3.local:32380, https://etcd-3.local:32379                \n690c4888e9365d4f, started, infra1, https://etcd-1.local:12380, https://etcd-1.local:12379                \n7bf52a4b91dbdccb, started, infra2, https://etcd-2.local:22380, https://etcd-2.local:22379 \n```\n\n[cfssl-install]: https://github.com/cloudflare/cfssl#installation\n[etcd-auth]: https://coreos.com/etcd/docs/latest/op-guide/authentication.html\n[etcd-releases]: https://github.com/coreos/etcd/releases\n[etcd-security]: https://coreos.com/etcd/docs/latest/op-guide/security.html\n[etcd-security-blog-post]: https://elweb.co/the-security-footgun-in-etcd/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericchiang%2Fetcd-security-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericchiang%2Fetcd-security-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericchiang%2Fetcd-security-guide/lists"}