Skip to content

Latest commit

 

History

History
666 lines (478 loc) · 18.6 KB

File metadata and controls

666 lines (478 loc) · 18.6 KB

Lab 4: Managing Secrets with Gopass

Overview

In this lab, you'll set up Gopass to manage your secrets securely. You'll use AGE encryption to protect your secrets and store them in a Git repository. We'll create an SSH keypair and store it in Gopass, which we'll later use with Chezmoi in Lab 5.

Time Required

45-60 minutes

Learning Objectives

  • Understand AGE encryption and why we use it
  • Install Gopass and AGE tools (we actually did this in lab 2 to save time - but we'll recap here)
  • Initialize a Gopass store with AGE encryption
  • Generate and store an SSH keypair
  • Store additional secrets (API tokens, etc.)
  • Back up your encrypted store to GitHub
  • Retrieve and use secrets from Gopass

Prerequisites

  • Completed Lab 3 (running your custom Bluefin VM)
  • GitHub Personal Access Token (from Lab 0)
  • GitHub account

Understanding Gopass and AGE

What is Gopass?

Gopass is a password manager for teams and individuals:

  • Command-line based
  • Stores encrypted secrets in Git repositories
  • Supports multiple encryption backends
  • Team-friendly (can share secrets)
  • Cross-platform

What is AGE?

AGE (Actually Good Encryption) is a modern encryption tool:

  • Simple and secure
  • Modern cryptography (Curve25519)
  • Better than GPG for most use cases
  • Easy to use
  • Small attack surface

Why AGE instead of GPG?

GPG (traditional):

  • Complex key management
  • Large attack surface
  • Complicated trust model
  • Hard to use correctly

AGE (modern):

  • Simple key pair (public/private)
  • Easy and straightforward to use
  • Designed for the most common use cases
  • Much harder to use incorrectly

Step 1: Install Gopass and AGE

As I have made these tools part of my workflow, I like to "bake them in" to the image that I've already created. If you look carefully at the recipe.yml from Lab 2, you'll notice that we actually already installed them then:

  - type: dnf
    ...
    install:
      packages:
        ...
        - gopass     # We'll need this for lab 4
        - age        # We'll need this for lab 4
        - chezmoi    # We'll need this for lab 5

Whilst this is my preferred option, if you don't want them to be part of the image you use (or if you want to use the "vanilla" Bluefin Linux image, you can install them using toolbox or Linuxbrew with the brew command - in both these cases, the tools will live in the user space (normally under your home directory) and you'll need to install them on every new machine you build).

Option B - Use Linuxbrew:

Linuxbrew is built into Bluefin based images (but be aware it's not there by default on some of the other immutable images such as Silverblue). Installing the required tools using Linuxbrew is as easy as:

# Install gopass and age
$ brew install gopass age

# Verify
$ gopass --version

**Option B - Use Toolbox **:

If you want to install the tools another way, as discussed we can use a Fedora toolbox container instead:

# Create a Fedora toolbox
$ toolbox create workshop

# Enter the toolbox
$ toolbox enter workshop

# Inside toolbox, install gopass and age
$ sudo dnf install -y gopass age

# Verify
$ gopass --version

For option C, all Gopass commands below should be run inside the toolbox.

Step 2: Set up a repository on GitHub

Before we proceed with any further local setup, let's set up a repository on GitHub where we'll sync our secrets to.

2.1 Create GitHub Repository

On GitHub:

  1. Go to https://github.com/new
  2. Repository name: gopass-store
  3. Description: "Encrypted password store"
  4. Visibility: Private (IMPORTANT!)
  5. Do NOT initialize with README
  6. Click "Create repository"

As this is a private repository, you will need to configure access to it, either using a Personal Access Token, or a Deploy Key if using SSH access. I'll assume we're using SSH access with a deploy key here, and that you're familiar with setting this up on GitHub, but if you need more assistance please refer to: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys#deploy-keys

For the rest of this guide, I'll assume we're using SSH to access our GitHub repo, and that our deploy key is called gopass-deploy-key.

Step 3: Initialise gopass

This is the central piece of this lab - getting gopass configured and running. We'll assume you're doing this for the first time, but if you are trying to recover from a failed attempt, please clear out existing gopass data first using the command:

$ rm -rf .config/gopass .local/share/gopass/

When that is done, you can run the following command to set up your AGE keys and gopass. Note that you will need to use some mechanism to ensure you can access your private GitHub repository over SSH - here I'm setting GIT_SSH_COMMAND at the time I run the command to demonstrate this approach, but you could also use ssh-agent, or a configuration in ~/.ssh - these options are left as an exercise for the participant.

$ GIT_SSH_COMMAND="ssh -i ~/gopass-deploy-key -o IdentitiesOnly=yes" gopass setup --crypto age

You will be guided through a wizard to set up the various parameters - see below an example of the wizard and responses suitable for the lab:

   __     _    _ _      _ _   ___   ___
 /'_ '\ /'_'\ ( '_'\  /'_' )/',__)/',__)
( (_) |( (_) )| (_) )( (_| |\__, \\__, \
'\__  |'\___/'| ,__/''\__,_)(____/(____/
( )_) |       | |
 \___/'       (_)

🌟 Welcome to gopass!
🌟 Initializing a new password store ...
🔐 Using crypto backend: age
💾 Using storage backend: gitfs
🔐 No useable cryptographic keys. Generating new key pair
🧪 Creating cryptographic key pair (age) ...
⚠ Do you want to enter a passphrase? (otherwise we generate one for you) [y/N/q]:
Passphrase: smokiness upheld gents impotent
⚠ You need to remember this very well!
Did you save your passphrase? [Y/n/q]:
✅ Key pair for age generated
⚠ 🔐 We need to unlock your newly created private key now! Please enter the passphrase you just generated.
✅ Key pair age1m9nkvjx2hns6rha2pr62cmm323yacd8kmyued3uq9q5n9fy82guq38lym4 validated
🔐 Cryptographic keys generated
🌟 Configuring your password store ...
Please enter an email address for password store git config []: sysadmin@example.com
❓ Do you want to add a git remote? [y/N/q]: y
Configuring the git remote ...
Please enter the git remote for your shared store []: git@github.com:<YOUR_USERNAME>/gopass-store.git
✅ Configuration written

Be sure you memorize or store securely the passphrase that you either entered or generated above - if you don't have this, you won't be able to recover your secrets!

Step 4: Backup your AGE Private Key

4.1 Backup your private key

Your AGE key should be backed up securely in the same manner as you would handle any other key-pair (e.g. an SSH key) - in the event of a loss of your system, the only copy of the private key is stored in your home directory tree and so you would be unable to decrypt your secrets on a new or replacement system without this.

To back up the key, run the following command:

$ cat ~/.config/gopass/age/identities | age -d
AGE-SECRET-KEY-1XXXXXX-XXXX-XXXXXXXXX-XXXXXX

Store the resulting string in a secure manner, consistent with how you back up other private keys. You can also back up the ~/.config/gopass/age/identities file directly, but you will need the decrypted string beginning AGE-SECRET-KEY in a DR scenario.

4.2 Understand the Keys

  • Public key: Starts with age1... - use this to encrypt - you saw this in the wizard output in Step 3
  • Secret key: Starts with AGE-SECRET-KEY-1... - use this to decrypt (retrieved above)

4.3 Extract Public Key

For convenience, you can see the public key in future by running:

$ gopass recipients
Hint: run 'gopass sync' to import any missing public keys
gopass
└── age1m9nkvjx2hns6rha2pr62cmm323yacd8kmyued3uq9q5n9fy82guq38lym4

Step 5: Create an SSH Keypair

Now let's create an SSH keypair that we'll store in Gopass.

5.1 Generate SSH Key

# Generate ED25519 SSH keypair (modern and secure)
$ ssh-keygen -t ed25519 -C "workshop@cfgmgmtcamp" -f /tmp/workshop_ssh_key -N ""

This creates:

  • /tmp/workshop_ssh_key - private key
  • /tmp/workshop_ssh_key.pub - public key

5.2 View the Keys

# Private key (keep secret!)
$ cat /tmp/workshop_ssh_key

# Public key (safe to share)
$ cat /tmp/workshop_ssh_key.pub

Step 6: Store Secrets in Gopass

6.1 Store SSH Private Key

# Export GIT_SSH_COMMAND to save having to specify it on each gopass command invocation
$ export GIT_SSH_COMMAND="ssh -i ~/gopass-deploy-key -o IdentitiesOnly=yes"

# Store SSH private key
$ gopass insert -m ssh/workshop_private_key < /tmp/workshop_ssh_key

6.2 Store SSH Public Key

# Store SSH public key
$ gopass insert -m ssh/workshop_public_key < /tmp/workshop_ssh_key.pub

6.3 Store GitHub Personal Access Token

# Store your GitHub token from Lab 0
$ gopass insert github/personal_access_token

# When prompted, paste your token
# Press Enter

# Enter it a second time to verify as requested

6.4 Store Additional Secrets (Optional)

Let's add a few more examples:

# Generate a random password
$ gopass generate web/example.com 32

# Add a note
$ gopass insert -m notes/ssh-usage
# Type your note, then Ctrl+D

Step 7: Retrieve Secrets

Learn how to retrieve secrets from Gopass.

7.1 List All Secrets

# List all stored secrets
$ gopass ls

Should show:

gopass
├── github/
│   └── personal_access_token
├── notes/
│   └── ssh-usage
├── ssh/
│   ├── workshop_private_key
│   └── workshop_public_key
└── web/
    └── example.com

7.2 Show a Secret

# Show SSH private key
$ gopass show ssh/workshop_private_key

# Show just the password (first line)
$ gopass show -o ssh/workshop_public_key

7.3 Copy to Clipboard

# Copy to clipboard (if clipboard is available)
$ gopass show -c web/example.com

# Secret is copied for 45 seconds, then clipboard is cleared

7.4 Use in Scripts

Gopass integrates well with scripts:

# Get secret in a script
TOKEN=$(gopass show -o github/personal_access_token)
echo "Token: $TOKEN"

# Use in a command
curl -H "Authorization: token $(gopass show -o github/personal_access_token)" \
  https://api.github.com/user

Step 8: Sync to GitHub

Your secrets are encrypted locally. Let's back them up to GitHub.

Step 8.1 Sync to GitHub

$ gopass sync
🚥 Syncing with all remotes ...
[<root>]
   gitfs pull and push ... OK (no changes)
   done
✅ All done

Note: The files in Git are encrypted! Even though the repository is on GitHub, only you can decrypt the secrets with your AGE key.

8.2 Verify on GitHub

  1. Go to https://github.com/YOUR_USERNAME/gopass-store
  2. You should see encrypted files (.gpg-id, .gopass.yml, and secret files)
  3. Open one of the secret files
  4. It should contain encrypted gibberish - this is correct!

Step 9: Understanding the Backup

9.1 What's in Git?

# View files
$ ls -la ~/.local/share/gopass/stores/root

You'll see:

  • .age-recipiets - Contains your AGE public key
  • ssh/ - Directory with encrypted secret files
  • github/ - Directory with encrypted files
  • etc.

9.2 View an Encrypted File

# Look at raw encrypted file
$ cat ~/.local/share/gopass/stores/root/ssh/workshop_private_key.age

It's encrypted! This is what's stored in Git.

9.3 The Security Model

What's secret:

  • Your AGE private key (~/.config/gopass/age/identities)
  • Decrypted secrets (only in memory when accessed)

What's not secret:

  • Encrypted files (safe to store in Git)
  • AGE public key (used only for encryption)
  • Directory structure (you can see secret names)

Important: Never commit your AGE private key to Git!

Step 10: Test Recovery Scenario

Let's simulate losing your machine and recovering your secrets.

10.1 Backup Your AGE Key

First, ensure your AGE key is backed up somewhere safe:

# Display your AGE key (copy this somewhere safe outside the VM)
$ cat ~/.config/gopass/age/identities | age -d

# In real life, you might:
# - Print it and store physically
# - Save to an encrypted USB drive
# - Store in a secure vault

CRITICAL: Without this key, you cannot decrypt your secrets!

10.2 Simulate Loss (Optional)

If you want to test recovery:

# Create a second toolbox to simulate a new machine
$ toolbox create workshop-recovery
$ toolbox enter workshop-recovery

# Install dependencies
$ sudo dnf install -y gopass age

# Toolbox has shared access to your existing home directory (where your gopass secrets live!), so we'll create a separate user under which to perform the recovery.
$ sudo useradd recovery
$ sudo cp gopass-deploy-key /home/recovery/
$ sudo chown recovery:recovery /home/recovery/gopass-deploy-key
$ sudo su - recovery

10.3 Add your gopass identity (public key) from earlier

In the new user account:

$ gopass age identities add
Enter the age identity starting in AGE-: <PASTE YOUR AGE SECRET KEY HERE>
Enter your PIN: <PASTE YOUR PASSPHRASE HERE>
Retype your PIN: <PASTE YOUR PASSPHRASE HERE>
⚠ New age identities are not automatically added to your recipient list, consider adding it using 'gopass recipients add age1m9nkvjx2hns6rha2pr62cmm323yacd8kmyued3uq9q5n9fy82guq38lym4'
⚠ If you do not add this recipient to the recipient list, make sure to re-encrypt using 'gopass fsck --decrypt' to properly support this identity

10.4 Complete the gopass setup

$ GIT_SSH_COMMAND="ssh -i ~/gopass-deploy-key -o IdentitiesOnly=yes" \
gopass --yes setup --remote git@github.com:YOUR_USERNAME/gopass-store.git \
 --name "James Freeman" --email "sysadmin@example.com" --crypto age

   __     _    _ _      _ _   ___   ___
 /'_ '\ /'_'\ ( '_'\  /'_' )/',__)/',__)
( (_) |( (_) )| (_) )( (_| |\__, \\__, \
'\__  |'\___/'| ,__/''\__,_)(____/(____/
( )_) |       | |
 \___/'       (_)

🌟 Welcome to gopass!
🌟 Initializing a new password store ...
🔐 Using crypto backend: age
💾 Using storage backend: gitfs
Enter your PIN:
Joining existing team ...
🌟 Configuring your password store ...
Enter your PIN:
✅ Configuration written
[gopass]Configuring git remote ...
[gopass]Cloning from the git remote ...
The authenticity of host 'github.com (20.26.156.215)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
[gopass]✅ Done. Joined Team "gopass"
[gopass]⚠ You still need to request access to decrypt secrets!

10.5 Verify Recovery

# List secrets
$ export GIT_SSH_COMMAND="ssh -i ~/gopass-deploy-key -o IdentitiesOnly=yes"
$ gopass ls

# Retrieve a secret
$ gopass show ssh/workshop_public_key

If you can decrypt and see your secrets, recovery was successful!

Step 11: Gopass Workflow

11.1 Adding New Secrets

# Add a new secret
$ gopass insert service/api-key

# Gopass automatically commits to Git
$ gopass show service/api-key  # Verify it's there

11.2 Syncing Changes

$ gopass sync

11.3 Searching Secrets

# Search for secrets
$ gopass search ssh

# Find secrets with fuzzy matching
$ gopass find github

11.4 Editing Secrets

# Edit an existing secret
$ gopass edit ssh/workshop_private_key

# This opens your default editor

10.5 Removing Secrets

# Remove a secret
$ gopass rm web/example.com

# Confirm deletion

Common Commands Reference

# List all secrets
$ gopass ls

# Show a secret
$ gopass show path/to/secret

# Show only password (first line)
$ gopass show -o path/to/secret

# Copy to clipboard
$ gopass show -c path/to/secret

# Insert new secret
$ gopass insert path/to/secret

# Insert multiline secret
$ gopass insert -m path/to/secret

# Generate random password
$ gopass generate path/to/secret 32

# Edit secret
$ gopass edit path/to/secret

# Delete secret
$ gopass rm path/to/secret

# Search secrets
$ gopass search keyword

# Sync with Git
$ gopass sync

Troubleshooting

Can't decrypt secrets

Error: no valid decryption key

Solution:

# Verify AGE key location
$ ls -la ~/.config/gopass/age/identities

Git push fails

Error: authentication failed

Solution:

  • Verify you're using Personal Access Token, not your GitHub password
  • Check token has repo permissions
  • Generate a new token if needed
  • If you are using SSH access, make sure you have exported GIT_SSH_COMMAND or otherwise configured your private key

Lost AGE Private key

This is critical - without your AGE private key, secrets are unrecoverable.

Prevention:

  • Back up key to secure location
  • Print and store physically
  • Use a password manager for the key itself
  • Consider storing encrypted in multiple locations

Security Best Practices

  1. Protect Your AGE Private Key:

    • Never commit to Git
    • Never share with others
    • Back up securely
    • Use strong filesystem permissions (600)
  2. Use Private Git Repositories:

    • Even though encrypted, use private repos
    • Reduces metadata exposure
    • Extra layer of security
  3. Unique Keys Per Person:

    • Don't share AGE keys between people
    • Use Gopass team features for sharing
  4. Regular Backups:

    • Push to Git regularly
    • Test recovery periodically
    • Keep AGE key backup up-to-date
  5. Audit Secret Access:

    • Review Git history
    • Know what secrets exist
    • Remove old/unused secrets

Key Takeaways

  • AGE provides simple, modern encryption
  • Gopass stores secrets encrypted in Git
  • Your AGE private key is the only thing you must protect
  • Encrypted secrets are safe to store in version control
  • Recovery requires your AGE key and Git repository
  • Gopass integrates well with scripts and automation
  • The command-line interface is simple and consistent

Verification Checklist

Before moving to the next lab:

  • AGE installed and key pair generated
  • Gopass installed and initialized with AGE
  • SSH keypair created and stored in Gopass
  • GitHub Personal Access Token stored in Gopass
  • Gopass store backed up to GitHub repository
  • Can retrieve secrets with gopass show
  • Understand the security model
  • AGE private key backed up securely

Next Steps

Excellent work! You now have a secure, version-controlled password store. In the next lab, we'll use Chezmoi to manage dotfiles and integrate it with Gopass to automatically deploy your SSH keys and configuration.


Previous: Lab 3: Installing and Running Your Custom Image Next: Lab 5: Managing Dotfiles with Chezmoi