Standalone script fetches SSH keys of GitHub repository collaborators or specified users and generates SOPS-compatible SSH key files.
Project description
github-to-sops integrates SOPS for secret management with github team/user identities. Use sops + github instead of having to operate Hashicorp Vault, AWS Secret Manager or click-managing github action secrets or fighting with GPG.
Why?
I think SOPS is the simplest way to manage secrets for team and individual projects, especially when combined with github as a key distribution mechanism.
This script makes it easy to setup SOPS as a lightweight gitops alternative to AWS Secrets Manager, AWS KMS, Hashicorp Vault.
SOPS is helpful to avoid the push-and-pray (https://dagger.io/ came up with this term and solution for it) pattern where all secrets for github actions are stored in Github Secrets such that nobody can repro stuff locally. With sops one can give github actions a single age private key and share all the development keys with rest of team on equal footing with CI/CD env.
Even though this github-to-sops implementation focuses on github it should be considered as part of a wider secrets-as-code (secrets-in-git + ssh&age) design pattern. It can be generalized for managing encrypted secrets in databases, hosting providers, logs, etc.
Requirements
- sops
- GitHub CLI (
gh) for repository collaborator lookup and for theinstallhelper. Rungh auth loginbefore using repository-based imports. If you pass recipients explicitly with--github-users,ghis not required for key import, but it is required forgithub-to-sops install. - Python3
- pip
Installation
This tool has two parts that need to be installed: github-to-sops itself, and sops.
Step 1: Install github-to-sops
The preferred way to install github-to-sops is with uv, a fast Python package installer:
uv pip install github-to-sops
As an alternative to installing, uv can also run github-to-sops directly. For example:
uv run github-to-sops -- import-keys > .sops.yaml
Step 2: Install sops
After installing github-to-sops, you need to install sops.
On Mac or Linux, github-to-sops provides a helper command to install sops for you:
github-to-sops install
The install helper uses gh release download to fetch sops release assets from getsops/sops, verifies the binary against the upstream SHA256 checksums file, and then installs it to /usr/local/bin/sops.
For other platforms or for manual installation, please see the official sops installation guide.
Development Setup
For development on a local checkout, use uv to create a virtual environment and install in editable mode.
This avoids externally-managed-environment errors on modern OSes.
Create and activate a virtual environment:
uv venv
source .venv/bin/activate
Then install in editable mode:
uv pip install -e .
Alternative: pip Installation
If you prefer not to use uv, you can install github-to-sops using pip:
pip install github-to-sops
Implementation
github-to-sops generates and maintains .sops.yaml file with comments indicating where the keys came from. Has updatekeys command to pull new secrets and re-encrypt files.
Idea for this originated in https://github.com/tarasglek/chatcraft.org/pull/319 after I got sick of devising a secure secret distribution scheme for every small project.
Contributions Welcome
- Tests
- Binary build for python-less environments
- Would be nice to add is ACLs and an integrity check to keys being used.
Examples:
I wrote an indepth explanation and screencasts on my blog post introducing github-to-sops.
GitHub authentication
github-to-sops uses GitHub collaborators for repository-based imports. It does not use GitHub contributors as secret recipients, because commit authors are not necessarily current trusted repository members.
For repository-based imports, install GitHub CLI and authenticate:
gh auth login
Alternatively, bypass repository lookup and pass explicit users:
github-to-sops --github-users alice,bob import-keys
Example workflow for secrets with github
Import all public keys for collaborators from an existing github project
github-to-sops import-keys > .sops.yaml
of if your repo isn't published to github or you aren't working inside a git checkout
github-to-sops import-keys --github-url https://github.com/tarasglek/chatcraft.org
lets see
cat .sops.yaml
creation_rules:
- key_groups:
- age:
# Generated by `github-to-sops import-keys` https://github.com/tarasglek/github-to-sops
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG... user1@host # user1
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQ... user2@host # user2
Put a sample secret in yaml
echo -e "secrets:\n SECRET_KEY: dontlook" | sops --input-type yaml --output-type yaml -e /dev/stdin > secrets.enc.yaml
Lets take a peek
head -n 9 secrets.enc.yaml
secrets:
SECRET_KEY: ENC[AES256_GCM,data:MKKR6B0h1iA=,iv:KegjC62NQxich1dtodVF3aVnchf/fB+KQbtETh+4CaY=,tag:2+5mk4YMKKxLqaCOpZVNSA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age19j4d6v9j7rx5fs629fu387qz4zmlpsqjexa4s08tkfrrmfdl5cwqjlaupd
^ is safe to commit!
sops -i secrets.enc.yaml is useful for interactive editing.
Bulk-updating secrets+keys when someone is added/removed from project
The updatekeys command pulls updated public keys for all team members from GitHub, updates all .sops.yaml files, and then refreshes all *.enc.yaml, *.enc.json, and *.enc.env files with the new keys. This is useful when a team member is added to or removed from the project, or when a team member adds or removes keys.
github-to-sops updatekeys
Usage:
github-to-sops -h
usage: github-to-sops [-h] [--version] [--github-users GITHUB_USERS]
{install,updatekeys,import-keys} ...
Manage GitHub SSH keys and generate SOPS-compatible SSH key files.
options:
-h, --help show this help message and exit
--version show program's version number and exit
--github-users GITHUB_USERS
Comma-separated list of GitHub usernames to fetch keys
for. This is a global option that can be used with
import-keys and updatekeys.
Commands:
{install,updatekeys,import-keys}
install Install sops binary for supported platforms (Linux and
Mac).
updatekeys Update team keys and re-encrypt all .sops.yaml and
*.enc.{json,yaml,env} files.
import-keys Import SSH keys of GitHub repository collaborators or
specified github users and output that info into a
useful format like sops or ssh authorized_keys
Example invocations:
- `github-to-sops import-keys --github-url https://github.com/tarasglek/chatcraft.org --key-types ssh-ed25519 --format sops`
- `github-to-sops import-keys --github-url https://github.com/tarasglek/chatcraft.org --format authorized_keys`
- `github-to-sops import-keys --local-github-checkout . --format sops --key-types ssh-ed25519`
- `github-to-sops updatekeys`
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file github_to_sops-3.1.1.tar.gz.
File metadata
- Download URL: github_to_sops-3.1.1.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0aa1ed9ce33596efc04effe841bb03d42b406970020e0a9b333ec6c015cf6e0
|
|
| MD5 |
48c46b92166d0670430279a99b7985fa
|
|
| BLAKE2b-256 |
2ef710d3266db6e06dccd526c1b7b2515448638f799e30b2f962b5e34cc789bc
|
Provenance
The following attestation bundles were made for github_to_sops-3.1.1.tar.gz:
Publisher:
publish.yml on tarasglek/github-to-sops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_to_sops-3.1.1.tar.gz -
Subject digest:
a0aa1ed9ce33596efc04effe841bb03d42b406970020e0a9b333ec6c015cf6e0 - Sigstore transparency entry: 1837367869
- Sigstore integration time:
-
Permalink:
tarasglek/github-to-sops@cca2574ae44c0b211da3f8943f7fce5edea20617 -
Branch / Tag:
refs/tags/v3.1.1 - Owner: https://github.com/tarasglek
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cca2574ae44c0b211da3f8943f7fce5edea20617 -
Trigger Event:
push
-
Statement type:
File details
Details for the file github_to_sops-3.1.1-py3-none-any.whl.
File metadata
- Download URL: github_to_sops-3.1.1-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77857806fce9163e978b56d6710fabeafd1c92663272044fa0791cd8ad154467
|
|
| MD5 |
ca7797e25308a62b793c2f7ccd73c98e
|
|
| BLAKE2b-256 |
a3775d05036b3747892e05b113e2969e2d7123dc3f6e78a948c3a1aae60a6fab
|
Provenance
The following attestation bundles were made for github_to_sops-3.1.1-py3-none-any.whl:
Publisher:
publish.yml on tarasglek/github-to-sops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_to_sops-3.1.1-py3-none-any.whl -
Subject digest:
77857806fce9163e978b56d6710fabeafd1c92663272044fa0791cd8ad154467 - Sigstore transparency entry: 1837368011
- Sigstore integration time:
-
Permalink:
tarasglek/github-to-sops@cca2574ae44c0b211da3f8943f7fce5edea20617 -
Branch / Tag:
refs/tags/v3.1.1 - Owner: https://github.com/tarasglek
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cca2574ae44c0b211da3f8943f7fce5edea20617 -
Trigger Event:
push
-
Statement type: