Skip to content

Secure secret management with SOPS + Yubikey PIV. Hardware-backed encryption with physical touch requirement. Team-friendly with offline master key backup.

License

Notifications You must be signed in to change notification settings

shamil2/sops-yubikey

Repository files navigation

SOPS + Yubikey PIV Setup

Secure secret management using SOPS with Yubikey PIV hardware keys and offline master key backup.

Features

  • πŸ” Physical Touch Required - Every decryption requires touching your Yubikey (prevents silent malware attacks)
  • πŸ”‘ Hardware-Backed Keys - Private keys never leave the Yubikey secure element
  • πŸ’Ύ Offline Master Key - Emergency backup stored safely offline
  • πŸ‘₯ Team-Friendly - Easy onboarding with individual Yubikeys per team member
  • πŸ”’ Modern Crypto - X25519 elliptic curve cryptography via age-plugin-yubikey

Quick Start

Prerequisites

macOS (Homebrew):

brew install sops age age-plugin-yubikey yubico-piv-tool

Linux (Debian/Ubuntu):

# Install SOPS
wget https://github.com/mozilla/sops/releases/download/v3.8.1/sops_3.8.1_amd64.deb
sudo dpkg -i sops_3.8.1_amd64.deb

# Install age
sudo apt install age

# Install Yubikey tools
sudo apt install yubikey-manager yubico-piv-tool

# Install age-plugin-yubikey (requires Rust)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install age-plugin-yubikey

Windows (WSL2 + Ubuntu):

# Enable WSL2 and install Ubuntu from Microsoft Store first
# Then follow Linux instructions above

Windows (Native - PowerShell):

# Install via Chocolatey
choco install sops age

# Download and install Yubikey tools from:
# https://www.yubico.com/support/download/yubikey-manager/

# Install age-plugin-yubikey (requires Rust)
# Install Rust from: https://rustup.rs/
cargo install age-plugin-yubikey

Setup (5 minutes)

# 1. Generate master key (backup offline!)
age-keygen -o master-key.txt

# 2. Change Yubikey PINs (default: 123456 / 12345678)
yubico-piv-tool -a change-pin
yubico-piv-tool -a change-puk

# 3. Generate Yubikey PIV key with touch policy
age-plugin-yubikey --generate \
  --slot 1 \
  --touch-policy always \
  --pin-policy always \
  --name "your-name"

# 4. Create identity file for SOPS
age-plugin-yubikey --identity > ~/.sops-age-keys.txt

# Add to shell profile (choose your shell):
# For zsh (macOS default):
echo 'export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt' >> ~/.zshrc && source ~/.zshrc

# For bash (Linux default):
echo 'export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt' >> ~/.bashrc && source ~/.bashrc

# For Windows PowerShell (add to $PROFILE):
# [System.Environment]::SetEnvironmentVariable('SOPS_AGE_KEY_FILE', "$env:USERPROFILE\.sops-age-keys.txt", 'User')

# 5. Configure SOPS (see .sops.yaml example in repo)

# 6. Test it!
echo "secret: password123" > test.yaml
sops -e test.yaml > test.enc.yaml
sops -d test.enc.yaml  # Touch Yubikey when LED blinks ✨

Daily Usage

# Edit secrets (touch Yubikey twice: open + save)
sops secrets.enc.yaml

# Decrypt to view
sops -d secrets.enc.yaml

# Encrypt new file
sops -e secrets.yaml > secrets.enc.yaml

Documentation

Why Yubikey PIV?

Traditional secret management often relies on keys stored on disk. With Yubikey PIV:

Security Feature Traditional Yubikey PIV
Physical touch required ❌ βœ…
Malware can silently decrypt βœ… ❌
User awareness of access ❌ βœ… (LED blinks)
Private key extractable βœ… ❌
Hardware-backed crypto ❌ βœ…

Example: If malware tries to decrypt secrets, your Yubikey LED blinks - you'll notice and can prevent the attack by not touching.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Encrypted Secret File          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
               β”œβ”€β”€β”€ Decryption ───┐
               β”‚                   β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   Master Age Key   β”‚    β”‚  Yubikey PIV     β”‚
    β”‚   (offline/safe)   β”‚    β”‚  + Touch + PIN   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Team Workflow

Adding Team Members

  1. Team member generates Yubikey PIV key
  2. Shares public recipient (age1yubikey1...)
  3. Team lead adds to .sops.yaml
  4. Re-encrypt all secrets: sops updatekeys secrets.enc.yaml
  5. Team member can now decrypt (with Yubikey touch)

Removing Team Members

  1. Remove their recipient from .sops.yaml
  2. Re-encrypt all secrets (revokes their access)
  3. Commit changes

CI/CD Integration

CI/CD can't provide physical touch, so use the master key:

# GitHub Actions example
- name: Decrypt secrets
  env:
    SOPS_AGE_KEY: ${{ secrets.SOPS_MASTER_KEY }}
  run: sops -d secrets.enc.yaml > secrets.yaml

Security Best Practices

βœ… DO:

  • Store master key offline (safe, password manager)
  • Use --touch-policy always for all Yubikeys
  • Change default PINs immediately
  • Re-encrypt when removing team members
  • Commit encrypted files to git

❌ DON'T:

  • Never commit master-key.txt
  • Never commit unencrypted secrets
  • Never disable touch policy
  • Never share Yubikey or PIN
  • Never ignore LED blink (signals secret access)

Example .sops.yaml

creation_rules:
  - path_regex: .*\.(yaml|json|env|ini|txt)$
    key_groups:
      - age:
          # Master key (offline backup, CI/CD)
          - age1u3hs6xmw09l50sjwzhngd098e23ysruhn5mus8lv2drr6evs9s8sn5ygnq
          # Team Yubikeys (daily use with touch)
          - age1yubikey1qd...  # Team member 1
          - age1yubikey1qw...  # Team member 2

Requirements

Hardware:

  • Yubikey 5 or newer (with PIV support)

Operating Systems:

  • macOS 10.15+ (Catalina or newer)
  • Linux (Ubuntu 20.04+, Debian 11+, Fedora, Arch, etc.)
  • Windows 10/11 (via WSL2 with Ubuntu, or native)

Software:

  • SOPS 3.8+
  • age 1.1+
  • age-plugin-yubikey 0.5+
  • yubico-piv-tool / yubikey-manager

Troubleshooting

"No identities found"

# Create identity file
age-plugin-yubikey --identity > ~/.sops-age-keys.txt
export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt

"Touch timeout"

  • Touch Yubikey more quickly when LED blinks (15 second timeout)

"Algorithm error"

# Try without pin-policy flag
age-plugin-yubikey --generate --slot 1 --touch-policy always --name "yourname"

See TROUBLESHOOTING.md for more solutions.

Contributing

Contributions welcome! Feel free to:

  • Report issues
  • Suggest documentation improvements
  • Share your team's workflow adaptations

Resources

License

This documentation is provided as-is for educational and practical use. Adapt it to your team's needs.

Support


Security Note: This setup provides strong security through hardware-backed keys and physical touch requirements. However, no system is perfect - always follow your organization's security policies and best practices.

About

Secure secret management with SOPS + Yubikey PIV. Hardware-backed encryption with physical touch requirement. Team-friendly with offline master key backup.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published