github-to-sops 2.0.0
Standalone (no-dependencies beyond Python) script fetches SSH keys of GitHub repository contributors and generates SOPS-compatible SSH key files.
License: MIT
Requires Python: >=3.8

github-to-sops integrates SOPS with github team/user identities. Use sops + github instead of having to operate Hashicorp Vault, AWS Secret Manager or just stuffing everything into 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](https://github.com/getsops/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](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) 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.

## Requirements

* [sops](https://github.com/getsops/sops)
* Python3
* [pip](https://pip.pypa.io/en/stable/installation/)

## 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`](https://github.com/astral-sh/uv), a fast Python package installer:
```bash
uv pip install github-to-sops
```

As an alternative to installing, `uv` can also run `github-to-sops` directly. For example:
```bash
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:
```bash
github-to-sops install
```

For other platforms or for manual installation, please see the [official sops installation guide](https://github.com/getsops/sops#installing).

### 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:
```bash
uv venv
source .venv/bin/activate
```
Then install in editable mode:
```bash
uv pip install -e .
```

### Alternative: pip Installation

If you prefer not to use `uv`, you can install `github-to-sops` using `pip`:
```bash
pip install github-to-sops
```

## Implementation

github-to-sops generates and maintains .sops.yaml file with comments indicating where the keys came from. Has refresh-secrets 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](https://taras.glek.net/post/github-to-sops-lighter-weight-secret-management/#heres-how-you-get-started).

## Env vars:

*  GITHUB_TOKEN: optional github token which helps avoid rate limiting.

I tried to make the code work without github tokens, but github requires them for private repos and does aggressive rate-limiting without them. See github docs on how to obtain GITHUB_TOKEN https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens


### Example workflow for secrets with github

Import all public keys for contributors from an existing github project
```bash
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
```bash
github-to-sops import-keys  --github-url https://github.com/tarasglek/chatcraft.org
```
lets see
```bash
cat .sops.yaml
```
```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

```bash
echo -e "secrets:\n  SECRET_KEY: dontlook" | sops --input-type yaml --output-type yaml  -e /dev/stdin > secrets.enc.yaml
```
Lets take a peek
```bash
head -n 9 secrets.enc.yaml
```
```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

```bash
github-to-sops refresh-secrets
```

## Usage:
```
github-to-sops -h
usage: github-to-sops [-h] [--version] [--github-users GITHUB_USERS]
                      {install,refresh-secrets,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 refresh-secrets.

Commands:
  {install,refresh-secrets,import-keys}
    install             Install sops binary for supported platforms (Linux and
                        Mac).
    refresh-secrets     Find all .sops.yaml files in the repo that are
                        managed by git and run `import-keys --inplace-edit
                        .sops.yaml` on them. Can be combined with
                        --github-users.
    import-keys         Import SSH keys of GitHub repository contributors 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 refresh-secrets`
```