diff --git a/tutorials/protect-github-ssh.mdx b/tutorials/protect-github-ssh.mdx index ebd18ba3..abc39a3e 100644 --- a/tutorials/protect-github-ssh.mdx +++ b/tutorials/protect-github-ssh.mdx @@ -1,5 +1,5 @@ --- -updated_at: October 05, 2026 +updated_at: October 13, 2026 title: Protect GitHub with SSH Certificates html_title: Protect GitHub Repositories with Hardware-Bound SSH Certificates description: Authenticate to GitHub with short-lived SSH certificates backed by your device's TPM or Secure Enclave, issued and managed by the Smallstep Agent. @@ -22,7 +22,7 @@ sequenceDiagram participant Git as git client participant GH as GitHub Agent->>CA: Request SSH user certificate (hardware-bound key) - CA->>Agent: Certificate with GitHub username principal + CA->>Agent: Certificate with GitHub username extension Git->>GH: git push (certificate via SSH agent socket) GH->>GH: Verify certificate against trusted CA GH->>Git: Access granted @@ -46,7 +46,7 @@ You will need: ## Sync users and their GitHub usernames -Smallstep issues each user an SSH certificate whose *principals* must include the user's GitHub username—that's how GitHub maps a certificate to a GitHub account. +Smallstep issues each user an SSH certificate that carries the user's GitHub username in the `login@github.com` extension—that's how GitHub maps a certificate to a GitHub account. To make the username available, configure your identity provider to sync users to Smallstep with a custom `githubUsername` attribute. @@ -117,25 +117,21 @@ echo "Authorization: Bearer [your API token]" > api_headers set -o history ``` -Next, choose the SSH authority that should issue your SSH certificates. -In the Smallstep dashboard, go to **Certificate Manager → Authorities**, open the authority, -and copy its **Authority ID** from the **Authority Settings** panel. - -Then create the credential with the [Create Credential](https://gateway.smallstep.com/v2025-01-01/operations/PostCredentials) endpoint: +Then create the credential with the [Create Endpoint Configuration](https://gateway.smallstep.com/v2025-01-01/operations/PostEndpointConfigurations) endpoint: ```bash curl -sH @api_headers --request POST \ - --url https://gateway.smallstep.com/api/credentials \ + --url https://gateway.smallstep.com/api/endpoint-configurations \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-smallstep-api-version: 2025-01-01' \ --data @- <<'EOF' | jq { - "slug": "github", - "certificate": { + "kind": "account", + "name": "GitHub", + "certificateInfo": { "type": "SSH_USER", - "authorityID": "[your authority ID]", - "fields": { + "details": { "keyId": { "deviceMetadata": "smallstep:identity", "static": "github" @@ -145,10 +141,9 @@ curl -sH @api_headers --request POST \ } } }, - "key": { + "keyInfo": { "protection": "HARDWARE_ATTESTED" }, - "managementMode": "agent", "policy": { "assurance": ["high"], "operatingSystem": ["macOS", "Windows", "Linux"] @@ -159,17 +154,26 @@ EOF Here's what the fields mean: -- **`certificate.type: "SSH_USER"`** issues SSH user certificates instead of X.509 certificates. -- **`fields.keyId`** sets the certificate's key ID, used for identification and audit logging. -- **`fields.principals`** populates the certificate's principals from device metadata. - `SSH.Principals` includes the user's SSH principals synced from your identity provider—including the `githubUsername` attribute you configured above—and `smallstep:identity` adds the email address of the user assigned to the device. -- **`key.protection: "HARDWARE_ATTESTED"`** generates the private key in the device's +- **`kind: "account"`** marks this as a credential that a person uses to access a protected resource—here, GitHub. +- **`certificateInfo.type: "SSH_USER"`** issues SSH user certificates instead of X.509 certificates. +- **`details.keyId`** sets the certificate's key ID, used for identification and audit logging. +- **`details.principals`** populates the certificate's principals from device metadata. + `SSH.Principals` adds the user's POSIX usernames and SSH group principals synced from your identity provider, + and `smallstep:identity` adds the email address of the user assigned to the device. +- **`keyInfo.protection: "HARDWARE_ATTESTED"`** generates the private key in the device's secure hardware (TPM or Secure Enclave), where it can never be exported. - **`policy`** selects the devices that receive this credential; here, high-assurance macOS, Windows, and Linux devices. +The request doesn't name an authority. +Smallstep issues these certificates from your team's SSH authority—the same authority [Smallstep SSH](../ssh/README.mdx) uses—so this credential works alongside Smallstep SSH. + +The GitHub username isn't one of the principals. +Smallstep adds it to each certificate automatically, in the `login@github.com` extension, +from the `githubUsername` attribute you configured above. + Once this credential is created, the Smallstep Agent on matching devices automatically requests -and renews hardware-bound SSH certificates with the appropriate GitHub username as a principal. +and renews hardware-bound SSH certificates that carry each user's GitHub username. # Step 2: Configure the enforcement point @@ -203,7 +207,7 @@ ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK... 5. Click **Add CA** The CA now appears in your list of SSH certificate authorities, -and any SSH certificate signed by your Smallstep CA with a valid GitHub username principal +and any SSH certificate signed by your Smallstep CA that carries a valid GitHub username will be accepted for authentication to your organization's repositories. For more information, @@ -347,12 +351,13 @@ git config --global url."org-[your org ID]@github.com:[your org]/".insteadOf "gi You can configure `git` to sign commits with the same hardware-protected SSH credential, providing cryptographic proof of commit authorship. -1. Tell Git to use SSH for signing, and set your signing key: +1. Tell Git to use SSH for signing, and set your signing key. + The `key::` prefix tells Git that the value is a public key, not a file path: ```bash git config --global gpg.format ssh step ssh list --raw | head -1 | step crypto key format --ssh - git config --global user.signingkey "[your SSH public key]" + git config --global user.signingkey "key::[your SSH public key]" ``` 2. Configure allowed signers, so `git` can verify signatures locally: @@ -393,4 +398,3 @@ For more, see [GitHub's documentation on commit signature verification](https:// If nothing is listed, confirm the device matches the credential's policy (assurance level, operating system, and tags), and see the [agent troubleshooting guide](../platform/troubleshooting-agent.mdx). -- In the Smallstep dashboard, confirm the user's device shows an issued SSH certificate.