{"id":28445178,"url":"https://github.com/spiffe/spire-server-attestor-tpm","last_synced_at":"2025-10-10T19:37:54.308Z","repository":{"id":285411993,"uuid":"958051884","full_name":"spiffe/spire-server-attestor-tpm","owner":"spiffe","description":"SPIRE Server Attestor TPM","archived":false,"fork":false,"pushed_at":"2025-06-01T11:56:12.000Z","size":563,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-06-29T20:39:21.677Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/spiffe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-31T15:06:24.000Z","updated_at":"2025-06-01T11:56:16.000Z","dependencies_parsed_at":"2025-03-31T16:39:12.413Z","dependency_job_id":"dc141716-bc2f-4143-a27a-a89f508a6199","html_url":"https://github.com/spiffe/spire-server-attestor-tpm","commit_stats":null,"previous_names":["spiffe/spire-server-attestor-tpm"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/spiffe/spire-server-attestor-tpm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiffe%2Fspire-server-attestor-tpm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiffe%2Fspire-server-attestor-tpm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiffe%2Fspire-server-attestor-tpm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiffe%2Fspire-server-attestor-tpm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spiffe","download_url":"https://codeload.github.com/spiffe/spire-server-attestor-tpm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiffe%2Fspire-server-attestor-tpm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279005032,"owners_count":26083827,"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-10T02:00:06.843Z","response_time":62,"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":[],"created_at":"2025-06-06T10:11:31.855Z","updated_at":"2025-10-10T19:37:54.300Z","avatar_url":"https://github.com/spiffe.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# SPIRE Server Attestor TPM\n\n[![Apache 2.0 License](https://img.shields.io/github/license/spiffe/helm-charts)](https://opensource.org/licenses/Apache-2.0)\n[![Development Phase](https://github.com/spiffe/spiffe/blob/main/.img/maturity/dev.svg)](https://github.com/spiffe/spiffe/blob/main/MATURITY.md#development)\n\nThis project enables SPIRE Agents to automatically attest the SPIRE server(s) via a trusted set of [TPMs](https://en.wikipedia.org/wiki/Trusted_Platform_Module).\n\nThis enables a large number of Workload nodes to easily establish trust during initial setup, or reestablish trust if they are powered down too long or if the server is broken too long without needing to touch the nodes.\n\nIt can also be used along with the spire-ha-agent to build an even higher level of HA trust domain.\n\n## Warning\n\nThis code is very early in development and is very experimental. Please do not use it in production yet. Please do consider testing it out, provide feedback, and maybe provide fixes.\n\n## Server Attestation\n\nWhen bootstrapping a SPIRE Agent to a SPIRE Server, proof that the Server is the correct one to trust must be established. Also, when trust is lost and must be reestablished, this procedure must be performed again. Server Attestation extends the built in support in SPIRE to allow fully automated bootstrapping/rebootstrapping in a plugable way.\n\nThis component implements this interface utilizing TPMs to attest the validity of the SPIRE Server to the SPIRE Agents. This enables fully hands off trust (re)establishment without 3rd parties. That is very important in setups where SPIRE is your bottom turtle of trust.\n\n## Minimal Architectural Diagram\n\nThere are multiple ways of setting this up. The simplest is diagrammed here:\n![diagram](diagram.png)\n\n## Components\n\n* spire-server-attestor-tpm-sign - spire-server plugin\n* spire-server-attestor-tpm-signer-unix - service\n* spire-server-attestor-tpm-signer-http - service (optional)\n* spire-server-attestor-tpm-verifier - spire-agent service\n\n### spire-server-attestor-tpm-sign\n\nSPIRE Server Bundle Publisher plugin. Recieves a bundle from the SPIRE Server. Signs it locally using the spire-server-attestor-tpm-signer-unix service, and optionally through a list of remote spire-server-attestor-tpm-signer-http services.  Even if the trust bundle hasn't updated, it will still push out new versions as their signatures get close to expiry.\n\n### spire-server-attestor-tpm-signer-unix\n\nRuns as root, has access to the TPM, listens for signing requests on a unix socket.\n\nThis allows other services to request trust bundles be signed by the TPM.\n\nStores the signed trust bundle in a configurable location for serving out to agents via http server (nginx, apache, etc).\n\nProtect the unix socket.\n\n### spire-server-attestor-tpm-signer-http\n\nListens on the network for trust bundle signing requests. Runs as non root. Accepts a trust bundle that must be already signed by an approved key. Forwards the request to the spire-server-attestor-tpm-signer-unix socket. An ip based filter can also be applied to block traffic so the service doesn't spend extra time decoding/key checking. Adds an additional signature for more trust.\n\n### spire-server-attestor-tpm-verifier\n\nRuns on each SPIRE Agent node. Provides a unix socket for it to fetch a trust bundle from for attesting the SPIRE Server. You configure the verifier with the HTTP URL to retrieve the signed trust bundle from, along with the TPM keys. It will verify the validity of the trust bundle, then return it to the SPIRE Agent if valid.\n\n## Prepare your TPMS\n\nThere is a minimum number of 1 TPM for setting up a system. For a standard SPIRE server setup, we recommend at minimum 2 TPMS. One primary, and one offline backup TPM.\n\nFor a spire-ha-agent based setup, we recommend a minimum number of 3 TPMs. 1 for each side of the HA trust domain, and one offline backup TPM.\n\nBackup TPMs can be used in place of a primary one, should the node/TPM fail and needs replacing in a timely manner.\n\n\n## Setup\n\n### Check that you don't have a key pair already on the TPM\n```\ntpm2_getcap handles-persistent | grep 0x81008006\n```\n\n### If you don't have a key, do the following to generate the key pair\n```\ntpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C 0x81000001\ntpm2_load -C 0x81000001 -u key.pub -r key.priv -c key.ctx\ntpm2_evictcontrol -C o -c key.ctx 0x81008006\n```\n\n``` Generate the public key file to copy to the other hosts\ntpm2_readpublic -c 0x81008006 -o pub.pem -f pem  -o \u003cmain.pem,backup.pem,a.pem,b.pem,etc here\u003e\n```\n\n### Distribute the public keys to:\n```\n/etc/spire/server-attestor-tpm/keys/\n```\n\n## Configuration\n\n### spire-server\n\nExample server.conf snippet:\n```\n    BundlePublisher \"signer\" {\n        plugin_cmd = \"/usr/bin/spire-server-attestor-tpm-sign\"\n        plugin_data {\n            # Additional URL's in which to use for signatures\n            urls = [\"http://1.2.3.4:8181/sign\"]\n\n            # Defaults\n            # socket = \"/var/run/spire/server-attestor-tpm/signer-unix.sock\"\n            # frequency = \"5m\"\n        }\n    }\n```\n\n### signer-unix\n\nExample signer-unix.conf\n```\nsocket: /var/run/spire/server-attestor-tpm/signer-unix.sock\ntpm-address: 0x81008006\nduration:  10m\ndir: /usr/share/nginx/html\n\n# filename: \"spiffetrustbundle.token\"\n# tmpfile: \"spiffetrustbundle.token.tmp\"\n\n# Issuer can be set. Defaults to the hostname of the machine its running on.\n# issuer: xxxx\n```\n\n### signer-http\n\nExample signer-http.conf:\n```\n# Location of the signer-unix service socket\nsocket: /var/run/spire/server-attestor-tpm/signer-unix.sock\n\n# Directory where keys will be looked up in. If relative, it will be relative to the location of this config file.\nkeydir: keys\n\n# Key to verify signatures against.\nprimary: a.pem\n\n# Backup key to allow for signatures. If seen, it will be logged.\nbackup: c.pem\n\n# Port and optional ip address to listen on\nlisten-addr: \":8181\"\n\n# Alowed ip addresses allowed to talk to the service. Used to prevent random nodes from causing too much cpu load verifying certs. Signed certs are still required for proper auth.\nallowed-addrs:\n- 127.0.0.1\n- spire-server.${SPIFFE_TRUST_DOMAIN}\n# - spire-server-a.${SPIFFE_TRUST_DOMAIN}\n# - spire-server-b.${SPIFFE_TRUST_DOMAIN}\n```\n\n### Verifier\n\n#### Standalone SPIRE Server\n\nExample verifier.conf\n```\nkeydir: keys\nsocket: /var/run/spire/server-attestor-tpm/verifier.sock\nkeyset:\n  main:\n    url: http://spire-server.${SPIFFE_TRUST_DOMAIN}/spiffetrustbundle.token\n    backup: backup.pem\n    chain:\n    - primary.pem\n```\n\nThen, in your spire agent.conf, in the agent section:\n```\ntrust_bundle_url = \"http://localhost/trustbundle?instance=main\"\ntrust_bundle_unix_socket = \"/var/run/spire/server-attestor-tpm/verifier.sock\"\n```\n\n#### SPIRE-HA-Agent setup\n\nExample verifier.conf\n```\nkeydir: keys\nsocket: /var/run/spire/server-attestor-tpm/verifier.sock\nkeyset:\n  a:\n    url: http://spire-server-a.${SPIFFE_TRUST_DOMAIN}/spiffetrustbundle.token\n    backup: backup.pem\n    chain:\n    - a.pem\n    - b.pem\n  b:\n    url: http://1.2.3.6/spiffetrustbundle.token\n    url: http://spire-server-b.${SPIFFE_TRUST_DOMAIN}/spiffetrustbundle.token\n    backup: backup.pem\n    chain:\n    - b.pem\n    - a.pem\n```\n\nThen, in your spire agent.conf for side a, in the agent section:\n```\ntrust_bundle_url = \"http://localhost/trustbundle?instance=a\"\ntrust_bundle_unix_socket = \"/var/run/spire/server-attestor-tpm/verifier.sock\"\n```\n\nAnd in your spire agent.conf for side b, in the agent section:\n```\ntrust_bundle_url = \"http://localhost/trustbundle/?instance=b\"\ntrust_bundle_unix_socket = \"/var/run/spire/server-attestor-tpm/verifier.sock\"\n```\n\nIf using the systemd units, you can instead use the following config for both sides:\n```\ntrust_bundle_url = \"http://localhost/trustbundle?instance=${INSTANCE}\"\ntrust_bundle_unix_socket = \"/var/run/spire/server-attestor-tpm/verifier.sock\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspiffe%2Fspire-server-attestor-tpm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspiffe%2Fspire-server-attestor-tpm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspiffe%2Fspire-server-attestor-tpm/lists"}