Skip to main content

A standalone secret management tool for multi-environment deployments with Google Secret Manager

Project description

Botmaro Secrets Manager

A standalone, environment-aware secret management tool built on Google Secret Manager (GSM). Designed for multi-environment deployments with support for both GitHub Actions workflows and local development.

Features

  • 🔐 Multi-environment support - Manage secrets across staging, prod, dev, and custom environments
  • 🎯 Project scoping - Organize secrets by project within environments
  • 🔄 Version control - Leverage GSM's built-in versioning
  • 🚀 CI/CD ready - Bootstrap secrets in GitHub Actions or any CI/CD pipeline
  • 🛠️ CRUD operations - Full create, read, update, delete support via CLI
  • 📦 Pip installable - Install as a standalone package
  • 🎨 Rich CLI - Beautiful, user-friendly command-line interface
  • 🔒 IAM integration - Automatic service account access management

Installation

From source (development)

# Clone the repository
git clone https://github.com/B9ice/botmaro-gcp-secret-manager.git
cd botmaro-gcp-secret-manager

# Install in development mode
pip install -e .

From PyPI (when published)

pip install botmaro-secrets-manager

Quick Start

1. Create a configuration file

Create a secrets.yml file defining your environments and secrets:

version: "1.0"

environments:
  staging:
    name: staging
    gcp_project: your-gcp-project-staging
    global_secrets:
      - name: API_KEY
        required: true
      - name: DATABASE_URL
        required: true

See secrets.example.yml for a complete example.

2. Bootstrap your environment

# Load all secrets for staging environment
secrets-manager bootstrap staging

# Bootstrap with project scope
secrets-manager bootstrap staging --project myapp

# Export to a .env file
secrets-manager bootstrap staging --output .env.staging

3. Manage secrets

# Set a secret
secrets-manager set staging.API_KEY --value "sk-123456"

# Set a project-scoped secret
secrets-manager set staging.myapp.DATABASE_URL --value "postgres://..."

# Get a secret
secrets-manager get staging.API_KEY --reveal

# List all secrets
secrets-manager list staging

# Delete a secret
secrets-manager delete staging.OLD_KEY --force

Usage

Command-Line Interface

Bootstrap Command

Load all secrets for an environment:

secrets-manager bootstrap <environment> [OPTIONS]

Options:
  --project, -p TEXT      Project name to scope secrets
  --config, -c TEXT       Path to secrets config file
  --export/--no-export    Export secrets to environment variables [default: True]
  --runtime-sa TEXT       Runtime service account to grant access
  --deployer-sa TEXT      Deployer service account to grant access
  --output, -o TEXT       Output file for .env format
  --verbose, -v           Verbose output

Examples:

# Bootstrap staging
secrets-manager bootstrap staging

# Bootstrap with service account access grants
secrets-manager bootstrap staging \
  --runtime-sa bot@project.iam.gserviceaccount.com \
  --deployer-sa deploy@project.iam.gserviceaccount.com

# Save to .env file
secrets-manager bootstrap prod --output .env.production

Set Command

Create or update a secret:

secrets-manager set <target> [OPTIONS]

Target format:
  - env.SECRET_NAME              (environment-scoped)
  - env.project.SECRET_NAME      (project-scoped)

Options:
  --value, -v TEXT     Secret value (or read from stdin)
  --config, -c TEXT    Path to secrets config file
  --grant, -g TEXT     Service account to grant access (can be repeated)

Examples:

# Set an environment-scoped secret
secrets-manager set staging.API_KEY --value "sk-123456"

# Set a project-scoped secret
secrets-manager set staging.orchestrator.DATABASE_URL --value "postgres://..."

# Read from stdin
echo "secret-value" | secrets-manager set staging.MY_SECRET

# Grant access to service accounts
secrets-manager set staging.API_KEY --value "sk-123" \
  --grant bot@project.iam.gserviceaccount.com \
  --grant deploy@project.iam.gserviceaccount.com

Get Command

Retrieve a secret value:

secrets-manager get <target> [OPTIONS]

Options:
  --version TEXT       Secret version to retrieve [default: latest]
  --config, -c TEXT    Path to secrets config file
  --reveal             Show the full secret value

Examples:

# Get latest version (masked by default)
secrets-manager get staging.API_KEY

# Reveal full value
secrets-manager get staging.API_KEY --reveal

# Get specific version
secrets-manager get staging.API_KEY --version 2 --reveal

List Command

List all secrets in an environment:

secrets-manager list <environment> [OPTIONS]

Options:
  --project, -p TEXT   Project name to filter by
  --config, -c TEXT    Path to secrets config file
  --reveal             Show secret values

Examples:

# List all staging secrets
secrets-manager list staging

# List project-specific secrets
secrets-manager list staging --project orchestrator

# Show values (masked by default)
secrets-manager list staging --reveal

Delete Command

Delete a secret:

secrets-manager delete <target> [OPTIONS]

Options:
  --config, -c TEXT    Path to secrets config file
  --force, -f          Skip confirmation

Examples:

# Delete with confirmation prompt
secrets-manager delete staging.OLD_API_KEY

# Force delete
secrets-manager delete staging.OLD_API_KEY --force

Grant Access Command

Grant access to all secrets in an environment or project:

secrets-manager grant-access <target> [OPTIONS]

Target format:
  - env                  (all environment-level secrets)
  - env.project          (all project-scoped secrets)

Options:
  --sa TEXT            Service account email to grant access (can be repeated)
  --config, -c TEXT    Path to secrets config file
  --force, -f          Skip confirmation prompt

Examples:

# Grant access to all staging secrets
secrets-manager grant-access staging \
  --sa bot@project.iam.gserviceaccount.com

# Grant to multiple service accounts
secrets-manager grant-access staging \
  --sa bot@project.iam.gserviceaccount.com \
  --sa deployer@project.iam.gserviceaccount.com

# Grant access to all project-specific secrets
secrets-manager grant-access staging.myapp \
  --sa myapp-runtime@project.iam.gserviceaccount.com

# Skip confirmation
secrets-manager grant-access staging --sa bot@project.iam.gserviceaccount.com --force

Note: This command grants the secretmanager.secretAccessor role, allowing the service account to read secret values.

GitHub Actions Integration

Example Workflow

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install secrets manager
        run: pip install -e .

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v1
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}

      - name: Bootstrap secrets
        run: |
          secrets-manager bootstrap staging \
            --runtime-sa botmaro-runner@project.iam.gserviceaccount.com \
            --config secrets.yml

      - name: Deploy application
        run: |
          # Your deployment commands here
          # All secrets are now available as environment variables
          echo "Deploying with SUPABASE_URL=$SUPABASE_URL"

Setting up initial secrets

Before running in GitHub Actions, you need to populate secrets using this tool's CLI.

Note: This tool is your interface to Google Secret Manager. You only need gcloud for authentication, not for managing secrets.

# 1. Authenticate to GCP (required for API access)
gcloud auth application-default login

# 2. Use secrets-manager CLI to create and manage secrets
secrets-manager set staging.SUPABASE_URL --value "https://xxx.supabase.co"
secrets-manager set staging.SUPABASE_ANON_KEY --value "eyJxxx..."
secrets-manager set staging.SUPABASE_SERVICE_ROLE_KEY --value "eyJxxx..."

# 3. Verify secrets were created
secrets-manager list staging --reveal

The secrets-manager CLI automatically creates secrets in Google Secret Manager with proper naming conventions and IAM permissions.

Configuration Reference

Environment Configuration

environments:
  <env-name>:
    name: string              # Environment name
    gcp_project: string       # GCP project ID
    prefix: string            # Optional: secret name prefix (default: botmaro-{env})

    global_secrets:           # Environment-level secrets
      - name: string          # Secret name
        description: string   # Optional description
        required: boolean     # Whether secret is required (default: true)
        default: string       # Optional default value

    projects:                 # Project-specific secrets
      <project-name>:
        project_id: string
        secrets:
          - name: string
            description: string
            required: boolean
            default: string

Secret Naming Convention

Secrets are stored in GSM using a double-hyphen (--) convention for hierarchical separation, while single hyphens (-) or underscores (_) are used within component names:

  • Environment-scoped: {prefix}--{SECRET_NAME}

    • Example: botmaro-staging--API_KEY
    • Example: my-longer-prefix--SUPABASE_URL
  • Project-scoped: {prefix}--{project}--{SECRET_NAME}

    • Example: botmaro-staging--orchestrator--DATABASE_URL
    • Example: my-company-prod--my-service--API_KEY

Where {prefix} defaults to botmaro-{environment} but can be customized.

Why double-hyphen?

  • Provides clear, unambiguous hierarchical separation
  • Easy to parse: secret_id.split('--')
  • GSM-compliant (only allows letters, numbers, -, and _)
  • Visually distinct from naming hyphens

Local Development

Setup

# Install dependencies
pip install -e ".[dev]"

# Set up secrets config
cp secrets.example.yml secrets.yml
# Edit secrets.yml with your configuration

# Authenticate to GCP
gcloud auth application-default login

Running locally

# Bootstrap local environment
secrets-manager bootstrap dev

# Or use a custom config
secrets-manager bootstrap dev --config ./my-secrets.yml

Python API

You can also use the library programmatically:

from secrets_manager import SecretsManager, SecretsConfig

# Load from config file
config = SecretsConfig.from_file("secrets.yml")
manager = SecretsManager(config)

# Bootstrap environment
secrets = manager.bootstrap(env="staging", export_to_env=True)

# Set a secret
manager.set_secret(
    env="staging",
    secret="API_KEY",
    value="sk-123456",
    grant_to=["bot@project.iam.gserviceaccount.com"]
)

# Get a secret
value = manager.get_secret(env="staging", secret="API_KEY")

# List secrets
secrets = manager.list_secrets(env="staging", project="myapp")

# Grant access to all secrets in an environment
result = manager.grant_access_bulk(
    env="staging",
    service_accounts=["bot@project.iam.gserviceaccount.com", "deployer@project.iam.gserviceaccount.com"]
)

IAM Permissions

The service account running the secrets manager needs:

  • secretmanager.admin - To create/update/delete secrets
  • iam.serviceAccountUser - To grant access to other service accounts

Grant these roles:

gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:YOUR_SA@PROJECT.iam.gserviceaccount.com" \
  --role="roles/secretmanager.admin"

Runtime service accounts need:

  • secretmanager.secretAccessor - To read secrets (granted automatically by the tool)

Troubleshooting

Authentication errors

Make sure you're authenticated to GCP:

gcloud auth application-default login

For CI/CD, use service account key or Workload Identity.

Secret not found

Check that:

  1. The secret exists in GSM: gcloud secrets list --project PROJECT_ID
  2. Your config file matches the environment name
  3. The GCP project ID is correct

Permission denied

Ensure your service account has the required IAM roles listed above.

Releasing

This project uses tag-based releases. When you're ready to publish a new version:

1. Update version and changelog

# Update version in pyproject.toml
vim pyproject.toml  # Change version = "0.1.0" to "0.1.1"

# Update CHANGELOG.md
vim CHANGELOG.md    # Add release notes under [Unreleased]

2. Commit changes

git add pyproject.toml CHANGELOG.md
git commit -m "Bump version to 0.1.1"
git push origin main

3. Create and push tag

# Create an annotated tag
git tag -a v0.1.1 -m "Release v0.1.1: Description of changes"

# Push the tag (this triggers PyPI publish!)
git push origin v0.1.1

What happens automatically:

  1. Version verification - Ensures tag matches pyproject.toml version
  2. Build package - Creates wheel and source distribution
  3. Publish to PyPI - Uploads to PyPI (requires PYPI_API_TOKEN secret)
  4. Create GitHub Release - Creates release page with changelog and assets

Manual publish (if needed)

You can also manually trigger the publish workflow from GitHub Actions UI:

  • Go to Actions → Publish to PyPI → Run workflow

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Support

For issues and questions:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

botmaro_secrets_manager-0.1.0.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

botmaro_secrets_manager-0.1.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file botmaro_secrets_manager-0.1.0.tar.gz.

File metadata

  • Download URL: botmaro_secrets_manager-0.1.0.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for botmaro_secrets_manager-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c3c3e9bae6d9b59ff6fcc113f1fbb062f25a0cd4b93f980000374f6aeaef42f9
MD5 e499fad8ad91f7a1d8685d38bb750310
BLAKE2b-256 5ab33b20b4881659a8e32124ded8ddea822cd99b29ff49fb3b9070bd2b73249a

See more details on using hashes here.

File details

Details for the file botmaro_secrets_manager-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for botmaro_secrets_manager-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 05ad1c8839316b7ff15bbcf9570915a7dfd70acd5ef6d175dfb911b3d2c7165a
MD5 81c5e66ff86ec7a4f651060572d56129
BLAKE2b-256 dc84a7de89af99e4e3378b696e27d7879f42e7d8d5f188f337eda454d3a784f0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page