{"id":46623879,"url":"https://github.com/shawntz/cassh","last_synced_at":"2026-03-07T22:02:38.107Z","repository":{"id":328422278,"uuid":"1110196162","full_name":"shawntz/cassh","owner":"shawntz","description":"💰 Ephemeral SSH key \u0026 cert manager for GitHub. Most developers juggle multiple GitHub accounts — work and personal, or multiple organizations. cassh manages them all from a single menu bar app.","archived":false,"fork":false,"pushed_at":"2026-02-01T01:06:50.000Z","size":11933,"stargazers_count":2,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-01T12:45:45.474Z","etag":null,"topics":["certificate-authority","devsecops","github","github-enterprise","ssh","ssh-key"],"latest_commit_sha":null,"homepage":"https://cassh.shawnschwartz.com/","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/shawntz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["shawntz"],"patreon":"ShawnSchwartz","buy_me_a_coffee":"shawntz"}},"created_at":"2025-12-04T21:07:27.000Z","updated_at":"2026-02-01T01:06:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shawntz/cassh","commit_stats":null,"previous_names":["shawntz/cassh"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/shawntz/cassh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shawntz%2Fcassh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shawntz%2Fcassh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shawntz%2Fcassh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shawntz%2Fcassh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shawntz","download_url":"https://codeload.github.com/shawntz/cassh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shawntz%2Fcassh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30233429,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T19:01:10.287Z","status":"ssl_error","status_checked_at":"2026-03-07T18:59:58.103Z","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":["certificate-authority","devsecops","github","github-enterprise","ssh","ssh-key"],"created_at":"2026-03-07T22:02:37.630Z","updated_at":"2026-03-07T22:02:38.102Z","avatar_url":"https://github.com/shawntz.png","language":"Go","funding_links":["https://github.com/sponsors/shawntz","https://patreon.com/ShawnSchwartz","https://buymeacoffee.com/shawntz"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003ecassh\u003c/h1\u003e\n\n  \u003cpicture\u003e\n    \u003cimg src=\"docs/assets/logo.png\" alt=\"cassh logo\" width=\"100\" height=\"100\"\u003e\n  \u003c/picture\u003e\n\n  \u003cp\u003e\u003cstrong\u003eSSH Key \u0026 Certificate Manager for GitHub\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003e\u003cem\u003eFor individuals and enterprises alike\u003c/em\u003e\u003c/p\u003e\n\n  \u003cp\u003e\n    Whether you're a solo developer managing personal projects or an enterprise team with hundreds of engineers,\u003cbr /\u003e\n    \u003ccode\u003ecassh\u003c/code\u003e brings security best practices to your SSH workflow — without the complexity.\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/shawntz/cassh/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/shawntz/cassh\" alt=\"Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/shawntz/cassh/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/shawntz/cassh\" alt=\"License\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://shawnschwartz.com/cassh\"\u003e\u003cimg src=\"https://img.shields.io/badge/docs-GitHub%20Pages-blue\" alt=\"Documentation\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n---\n\n## Get Started in 60 Seconds\n\n**Personal GitHub.com users** — no server required:\n\n```bash\n# 1. Install GitHub CLI (if you haven't)\nbrew install gh\ngh auth login\n\n# 2. Install cassh\nbrew tap shawntz/cassh\nbrew install --cask cassh\n\n# 3. Launch cassh — setup wizard opens automatically — done!\n```\n\n**Enterprise users** — see [Server Setup](https://shawnschwartz.com/cassh/server-setup/) for CA and Entra configuration.\n\n---\n\n## Why cassh?\n\n### For Individual Developers\n\nYou might think: *\"I already use `gh` to upload my SSH key — why do I need this?\"*\n\nThe `gh` CLI is great for the initial setup, but it doesn't manage your keys:\n\n| The Problem | Without cassh | With cassh |\n|-------------|---------------|------------|\n| **Key lifecycle** | Keys live forever until you manually delete them | Automatic rotation (4 hours to 90 days) |\n| **Laptop lost/stolen** | Your key still works until you notice and revoke it | Key auto-expires per your policy |\n| **Shared/work computer** | That SSH key might still be there months later | Set short rotation for shared environments |\n| **Multiple machines** | Different keys everywhere, no central management | Same workflow on every Mac |\n| **SSH config** | Manually edit `~/.ssh/config` for each account | Automatic configuration |\n\n\u003e **Security isn't just for enterprises.** Your personal GitHub account has access to your private repos, your contributions to other projects, and possibly deploy keys. Treat it accordingly.\n\n\n### For Enterprise Teams\n\nPermanent SSH keys are a security liability:\n\n| Scenario | With Permanent Keys | With cassh |\n|----------|---------------------|------------|\n| **Laptop lost** | Manual revocation required, often missed | Certificate expires automatically |\n| **Employee offboarding** | Hunt down and revoke all their keys | Certificates expire within hours |\n| **Compliance audit** | \"When was this key last rotated?\" | Full lifecycle tracking |\n| **Key compromise** | Blast radius until detected | Limited to certificate validity window |\n\ncassh issues **12-hour certificates** signed by your internal CA. No revocation lists to manage, no keys to track, no manual intervention needed.\n\n---\n\n## One App, All Your GitHub Accounts\n\nMost developers juggle multiple GitHub accounts — work and personal, or multiple organizations. cassh manages them all from a single menu bar app.\n\n- **Enterprise connections** use certificates that auto-expire\n- **Personal connections** use keys with configurable rotation\n- **Each connection** gets its own SSH key and config entry\n- **Status at a glance** — green means you're good, yellow means expiring soon, red means action needed\n\n---\n\n## Features\n\n| Feature | Personal | Enterprise |\n|---------|:--------:|:----------:|\n| One-click setup wizard | ✓ | ✓ |\n| Automatic SSH config | ✓ | ✓ |\n| Per-connection Git identity | ✓ | ✓ |\n| Menu bar status indicator | ✓ | ✓ |\n| Key/cert rotation | ✓ (configurable) | ✓ (12h default) |\n| Multi-account support | ✓ | ✓ |\n| Revoke \u0026 renew from menu bar | ✓ | ✓ |\n| Dotfiles-friendly config | ✓ | ✓ |\n| Microsoft Entra SSO | — | ✓ |\n| CA-signed certificates | — | ✓ |\n| MDM deployment (PKG) | — | ✓ |\n\n---\n\n## How It Works\n\n### Personal Flow (GitHub.com)\n\n```\nDownload cassh → Launch → Setup Wizard → Enter GitHub username → Done\n```\n\nBehind the scenes:\n1. cassh generates an Ed25519 SSH key\n2. Uploads it to GitHub via `gh ssh-key add`\n3. Configures `~/.ssh/config` automatically\n4. Tracks key age and rotates per your policy\n5. On rotation: deletes old key from GitHub, generates new key, uploads new key\n\n### Enterprise Flow (GitHub Enterprise)\n\n```\nClick menu bar → Generate Certificate → SSO login → Certificate installed\n```\n\nBehind the scenes:\n1. Opens browser to your cassh server\n2. Authenticates via Microsoft Entra ID\n3. Server signs your public key with the CA (includes `login@HOSTNAME` extension)\n4. Certificate returned and installed automatically via `cassh://` URL scheme\n5. Certificate expires in 12 hours — repeat as needed\n\n**Setup**: Just paste any SSH clone URL from your GitHub Enterprise (e.g., `user_123@github.company.com:org/repo.git`) and cassh extracts the hostname and SCIM-provisioned username automatically.\n\n---\n\n## Quick Start\n\n### Personal Users\n\n1. **Install prerequisites:**\n   ```bash\n   brew install gh\n   gh auth login\n   ```\n\n2. **Install cassh** via Homebrew:\n   ```bash\n   brew tap shawntz/cassh\n   brew install --cask cassh\n   ```\n\n3. **Launch** — the setup wizard opens automatically\n\n4. **Add Personal Account** — enter your GitHub username, choose rotation policy\n\n5. **Done!** — `git clone` your repos and go\n\n### Enterprise Users\n\nSee the **[Full Documentation](https://shawnschwartz.com/cassh)** for:\n- [Server Setup](https://shawnschwartz.com/cassh/server-setup/) — CA keys, Entra app configuration\n- [Deployment](https://shawnschwartz.com/cassh/deployment/) — Fly.io, Render, Railway, VPS\n- [Client Distribution](https://shawnschwartz.com/cassh/client/) — MDM deployment with PKG\n\n---\n\n## Configuration\n\ncassh stores your connections in a simple TOML config file. The config is **dotfiles-friendly** — store it in `~/.config/cassh/config.toml` to back up with your dotfiles.\n\n```toml\n# ~/.config/cassh/config.toml\n\n[[connections]]\nid = \"personal-github\"\ntype = \"personal\"\nname = \"Personal GitHub\"\ngithub_host = \"github.com\"\ngithub_username = \"yourusername\"\nssh_key_path = \"~/.ssh/cassh_personal_id_ed25519\"\nkey_rotation_hours = 168  # Rotate every 7 days\n\n[[connections]]\nid = \"enterprise-work\"\ntype = \"enterprise\"\nname = \"Work GitHub\"\nserver_url = \"https://cassh.yourcompany.com\"\ngithub_host = \"github.yourcompany.com\"\ngithub_username = \"user_123\"  # SCIM-provisioned username from SSH clone URL\nssh_key_path = \"~/.ssh/cassh_work_id_ed25519\"\nssh_cert_path = \"~/.ssh/cassh_work_id_ed25519-cert.pub\"\n```\n\n**Git Identity**: cassh can also manage per-connection git identities. When you add a connection, optionally specify your `user.name` and `user.email`. cassh uses Git's `includeIf` to automatically apply the correct identity based on the repo's remote URL. Your work repos use your work email, personal repos use your personal email — automatically.\n\nSee the **[Configuration Reference](https://shawnschwartz.com/cassh/configuration/)** for all options, or check out [`config.example.toml`](config.example.toml) for a complete example.\n\n---\n\n## Roadmap\n\nSee the [full roadmap](https://shawnschwartz.com/cassh/roadmap/) for details.\n\n| Status | Feature |\n|--------|---------|\n| :white_check_mark: | GitHub Enterprise SSH certificates |\n| :white_check_mark: | GitHub.com personal SSH key management |\n| :white_check_mark: | Automatic key rotation with configurable policies |\n| :white_check_mark: | Multi-account support (enterprise + personal) |\n| :white_check_mark: | Setup wizard for first-run configuration |\n| :white_check_mark: | macOS menu bar app with connection status |\n| :white_check_mark: | Microsoft Entra ID (Azure AD) SSO |\n| :construction: | Policy integrity verification |\n| :memo: | GitLab support |\n| :memo: | Bitbucket support |\n| :memo: | Linux support |\n\n**Legend:** :white_check_mark: Complete | :construction: In Progress | :memo: Planned\n\n---\n\n## Security\n\n\u003e [!CAUTION]\n\u003e **For Enterprise deployments:**\n\u003e - **Protect your CA private key** — it can sign certificates for anyone\n\u003e - **Use HTTPS** — OAuth tokens are transmitted\n\u003e - **Restrict Entra app** — limit which users can authenticate\n\u003e - Review access logs regularly\n\n\u003e [!TIP]\n\u003e **For Personal users:**\n\u003e - Use a short rotation policy (4-24h) on shared or work computers\n\u003e - Use a longer policy (7-90 days) on personal machines you control\n\u003e - cassh stores keys in `~/.ssh/` with proper permissions (0600)\n\n---\n\n## Architecture\n\n### GitHub Enterprise Flow (Certificates)\n\n```mermaid\nflowchart LR\n    subgraph Client\n        A[Menu Bar App]\n    end\n\n    subgraph Server\n        B[cassh Server]\n        C[Internal CA]\n    end\n\n    subgraph External\n        D[Microsoft Entra ID]\n        E[GitHub Enterprise]\n    end\n\n    A --\u003e|1. Request cert| B\n    B --\u003e|2. OIDC auth| D\n    D --\u003e|3. Identity verified| B\n    B --\u003e|4. Sign pubkey| C\n    C --\u003e|5. SSH certificate| B\n    B --\u003e|6. Return cert| A\n    A --\u003e|7. SSH with cert| E\n```\n\n### GitHub.com Personal Flow (SSH Keys)\n\n```mermaid\nflowchart LR\n    subgraph Client\n        A[Menu Bar App]\n        B[gh CLI]\n    end\n\n    subgraph External\n        C[GitHub.com]\n    end\n\n    A --\u003e|1. Generate SSH key| A\n    A --\u003e|2. Upload via gh| B\n    B --\u003e|3. Add to GitHub| C\n    A --\u003e|4. SSH with key| C\n    A -.-\u003e|5. On rotation: delete old, upload new| B\n```\n\n---\n\n## Support the Project\n\n`cassh` is built and maintained by [Shawn Schwartz](https://shawnschwartz.com), a PhD candidate in Psychology at Stanford. By day, he builds software for cognitive neuroscience research. By night, he builds security tools like this one.\n\nIf `cassh` saved you time or made your workflow more secure:\n\n- [Sponsor on GitHub](https://github.com/sponsors/shawntz)\n- Star this repo and share it with others\n\nEvery bit of support helps me justify the time spent on this free and open-source side project instead of my dissertation.\n\n---\n\n## Why Open Source?\n\nSecurity tooling should be auditable. You shouldn't have to trust a black box with your SSH authentication.\n\nContributions welcome! Check out [CONTRIBUTING.md](CONTRIBUTING.md) to get started.\n\n---\n\n## License\n\nApache 2.0 — See [LICENSE](LICENSE) for details. © Shawn Schwartz, 2025.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshawntz%2Fcassh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshawntz%2Fcassh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshawntz%2Fcassh/lists"}