Workspace-Verschlüsselung¶
Polycrate bietet eine eingebaute Verschlüsselung für sensible Workspace-Daten, die es Teams ermöglicht, Secrets sicher in Git-Repositories zu speichern und zu teilen. Die Verschlüsselung basiert auf age, einem modernen, sicheren Verschlüsselungstool.
Überblick¶
Das Workspace Encryption Feature verschlüsselt folgende sensible Dateien:
secrets.poly- Block-Konfiguration mit sensiblen Werten- Workspace-weite Secrets - Dateien in
artifacts/secrets/(z.B.kubeconfig.yml,id_rsa) - Block-spezifische Secrets - Dateien in
artifacts/secrets/BLOCKNAME/
Verschlüsselte Dateien erhalten die Endung .age und können sicher in Git committet werden. Die Originaldateien werden durch .gitignore automatisch vom Commit ausgeschlossen.
Architektur¶
graph TB
User[Entwickler] -->|polycrate workspace encrypt| CLI[Polycrate CLI]
CLI -->|age encryption| Age[filippo.io/age]
CLI -->|prüft Key-Quellen| API[Polycrate API]
CLI -->|prüft Key-Quellen| ENV[WORKSPACE_ENCRYPTION_KEY]
CLI -->|prüft Key-Quellen| Prompt[Interaktiver Prompt]
API -->|Priority 1| Key[Encryption Key]
ENV -->|Priority 2| Key
Prompt -->|Priority 3| Key
Age -->|verschlüsselt| Files[secrets.poly<br/>artifacts/secrets/**]
Files -->|erstellt| Encrypted[secrets.poly.age<br/>artifacts/secrets/**/*.age]
Encrypted -->|sicher in| Git[Git Repository]
CLI -->|aktualisiert| Gitignore[.gitignore]
CLI -->|erstellt| Marker[.workspace-encrypted]
CLI -->|installiert| Hook[Pre-Commit Hook]
Hook -->|blockiert| Unencrypted[Unverschlüsselte<br/>Secrets]
Hook -->|erlaubt| Encrypted
style API fill:#90EE90
style ENV fill:#FFD700
style Prompt fill:#FFA500
style Key fill:#87CEEB
style Encrypted fill:#98FB98
style Git fill:#DDA0DD
style Hook fill:#FF6B6B
style Unencrypted fill:#FFB6B6 Key-Resolution Priority (höchste → niedrigste):
- Polycrate API - Encryption Credential automatisch vom API-Workspace abrufen
- Umgebungsvariable -
WORKSPACE_ENCRYPTION_KEY(Fallback wenn API nicht verfügbar) - Interaktiver Prompt - Manuelle Key-Eingabe (letzter Fallback, max. 3 Versuche)
Workspace Directory Layout mit Secrets¶
workspace/
├── workspace.poly # Öffentliche Workspace-Config
├── secrets.poly # ❌ Unverschlüsselt - NICHT in Git
├── secrets.poly.age # ✅ Verschlüsselt - IN GIT
├── .workspace-encrypted # ✅ Encryption Marker - IN GIT
├── .gitignore # Automatisch verwaltet
│
└── artifacts/
└── secrets/ # Secret-Artifacts Root
│
├── kubeconfig.yml # ❌ Workspace-wide, unverschlüsselt
├── kubeconfig.yml.age # ✅ Workspace-wide, verschlüsselt
├── id_rsa # ❌ SSH Private Key
├── id_rsa.age # ✅ SSH Private Key (verschlüsselt)
├── id_rsa.pub # ❌ SSH Public Key
├── id_rsa.pub.age # ✅ SSH Public Key (verschlüsselt)
│
└── myblock/ # Block-spezifische Secrets
├── secret.txt # ❌ Unverschlüsselt
├── secret.txt.age # ✅ Verschlüsselt
├── database.pwd # ❌ Unverschlüsselt
└── database.pwd.age # ✅ Verschlüsselt
Regel: Nur .age-Dateien und .workspace-encrypted dürfen in Git committet werden.
Erste Schritte¶
1. Workspace initialisieren¶
mkdir my-workspace
cd my-workspace
polycrate workspace init --with-name my-workspace --with-organization my-org
2. Secrets erstellen¶
secrets.poly - Block-Konfiguration¶
Die secrets.poly Datei enthält sensitive Block-Konfigurationswerte, die die Werte aus workspace.poly überschreiben:
# secrets.poly - Sensitive Block-Config-Overrides
blocks:
- name: my-database-block
config:
# Public-Werte können überschrieben werden
database_port: 5432
# Secret-Werte werden hinzugefügt
database_password: "supersecret123"
admin_password: "verysecure456"
- name: my-api-block
config:
api_token: "tok_abc123xyz789"
ssh_private_key: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
Merge-Priorität:
Die secrets.poly hat die höchste Priorität und überschreibt alle anderen Konfigurationswerte.
Workspace-weite Secrets¶
# Kubernetes-Konfiguration
cat > artifacts/secrets/kubeconfig.yml << EOF
apiVersion: v1
kind: Config
clusters:
- name: production-cluster
cluster:
server: https://k8s.example.com
certificate-authority-data: LS0t...
EOF
# SSH-Keys (falls nicht schon vorhanden)
ssh-keygen -t rsa -b 4096 -f artifacts/secrets/id_rsa -N ""
Block-spezifische Secrets¶
# Secrets für einen spezifischen Block
mkdir -p artifacts/secrets/my-database-block
echo "postgres://user:pass@host/db" > artifacts/secrets/my-database-block/connection-string.txt
echo "backup-secret-key-123" > artifacts/secrets/my-database-block/backup-key.txt
3. Verschlüsseln¶
# Key von Polycrate API holen (automatisch wenn konfiguriert)
# ODER: Key als Umgebungsvariable setzen
export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-..."
# Alle Secrets verschlüsseln
polycrate workspace encrypt
Output:
Found 5 files to encrypt
Encrypted: secrets.poly -> secrets.poly.age
Encrypted: artifacts/secrets/kubeconfig.yml -> artifacts/secrets/kubeconfig.yml.age
Encrypted: artifacts/secrets/id_rsa -> artifacts/secrets/id_rsa.age
Encrypted: artifacts/secrets/id_rsa.pub -> artifacts/secrets/id_rsa.pub.age
Encrypted: artifacts/secrets/my-database-block/connection-string.txt -> artifacts/secrets/my-database-block/connection-string.txt.age
Workspace encryption completed successfully
Was passiert bei der Verschlüsselung:
- Alle unverschlüsselten Secrets werden mit age verschlüsselt
- Verschlüsselte
.age-Dateien werden erstellt - Original-Dateien werden gelöscht
.gitignorewird automatisch aktualisiert.workspace-encryptedMarker wird erstellt/aktualisiert
4. In Git committen¶
In Git sind jetzt:
- ✅
secrets.poly.age - ✅
artifacts/secrets/*.age - ✅
.workspace-encrypted - ✅
.gitignore - ❌ KEINE unverschlüsselten Secrets!
CLI-Befehle¶
polycrate workspace encrypt¶
Verschlüsselt alle sensiblen Workspace-Dateien.
Key-Quellen (in Prioritätsreihenfolge):
- Polycrate API (automatisch wenn
api.enabled: true) WORKSPACE_ENCRYPTION_KEYUmgebungsvariable- Interaktiver Prompt (wenn Key nicht gefunden)
Optionen: - Keine zusätzlichen Optionen erforderlich - Key wird automatisch aus der besten verfügbaren Quelle geladen
Beispiele:
# Mit API-Key (automatisch)
polycrate workspace encrypt
# Mit Umgebungsvariable
export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-..."
polycrate workspace encrypt
# Mit interaktivem Prompt (keine ENV gesetzt)
polycrate workspace encrypt
# > Workspace-Key eingeben (Versuch 1 von 3): ****
polycrate workspace decrypt¶
Entschlüsselt alle verschlüsselten Workspace-Dateien.
Was passiert bei der Entschlüsselung:
- Alle
.age-Dateien werden entschlüsselt - Original-Dateien werden wiederhergestellt
.age-Dateien werden gelöscht (lokal)- Workspace ist nun lokal nutzbar
Beispiel:
Output:
Found 5 encrypted files to decrypt
Decrypted: secrets.poly.age -> secrets.poly
Decrypted: artifacts/secrets/kubeconfig.yml.age -> artifacts/secrets/kubeconfig.yml
Decrypted: artifacts/secrets/id_rsa.age -> artifacts/secrets/id_rsa
Decrypted: artifacts/secrets/id_rsa.pub.age -> artifacts/secrets/id_rsa.pub
Decrypted: artifacts/secrets/my-database-block/connection-string.txt.age -> artifacts/secrets/my-database-block/connection-string.txt
Workspace decryption completed successfully
polycrate workspace status¶
Zeigt den Verschlüsselungsstatus des Workspace an.
Ausgabe:
Workspace Encryption Status
============================
Workspace: https://polycrate.example.com/workspaces/3fc897cd-...
UUID: 3fc897cd-f557-4f48-b5a3-6aa0c5e49fe6
🔑 Key Status: ✅ Key available
Key ID: age12e956sgdpsxh...
Source: Polycrate API (priority 1)
📁 File Status:
Encrypted files:
✅ secrets.poly.age
✅ artifacts/secrets/kubeconfig.yml.age
✅ artifacts/secrets/id_rsa.age
✅ artifacts/secrets/my-database-block/connection-string.txt.age
🔒 Security Status:
.gitignore: ✅ Properly configured
Git repo: ✅ Detected
Branch: main
Commit: 923aaccb (Add workspace config)
Remote: ↑2 ahead
Changes: 3 staged, 0 unstaged, 0 untracked
💡 Recommendations:
- Workspace is properly encrypted and ready to commit
Key-Quellen-Anzeige wenn kein Key gefunden:
🔑 Key Status: ❌ No key found
Key sources checked (in priority order):
1. Polycrate API: ✅ Encryption credential found
- ID: cred-abc123
- Kind: workspace-encryption
- State: READY
2. Environment variable WORKSPACE_ENCRYPTION_KEY: ❌ Not set
3. Interactive prompt: Available on demand
Polycrate API Integration¶
Die Polycrate API bietet zentrales Key-Management für Workspace Encryption und ist die empfohlene Lösung für Teams.
Funktionsweise¶
Wenn die API-Integration aktiviert ist (api.enabled: true), ruft die Polycrate CLI automatisch den Workspace Encryption Key von der API ab. Dies hat die höchste Priorität in der Key-Resolution und überschreibt lokale Umgebungsvariablen.
Key-Resolution-Flow mit API:
- CLI prüft, ob API konfiguriert ist
- CLI fragt API nach Workspace Credentials vom Typ
workspace-encryption - API liefert age-kompatiblen Private Key zurück
- CLI verwendet Key automatisch für Ver-/Entschlüsselung
Credential-Speicherung:
Der Encryption Key wird als Workspace Credential in der API gespeichert. Die API verwaltet:
- Private Key (
ssh_private_key): age Secret Key für Ver-/Entschlüsselung - Public Key (
ssh_public_key): age Public Key (abgeleitet vom Private Key) - State: READY, PENDING oder ERROR
- Metadata: Workspace-Zuordnung, Erstellungsdatum, etc.
Vorteile der API-Integration:
- ✅ Automatischer Key-Abruf - Keine manuelle Key-Verwaltung nötig
- ✅ Zentrales Team-Management - Ein Key für alle Teammitglieder
- ✅ Workspace-spezifisch - Jeder Workspace hat seinen eigenen Key
- ✅ State-Tracking - Überwachung des Credential-Status
- ✅ Audit-Logging - Nachvollziehbarkeit aller Key-Zugriffe
- ✅ Key-Rotation - Zentrale Aktualisierung ohne lokale Änderungen
Für Details zur API-Konfiguration, Authentifizierung und Credential-Verwaltung siehe Polycrate API Dokumentation.
Team-Workflow¶
Developer A (Initial Setup)¶
# 1. Workspace erstellen
git clone <repo>
cd workspace
polycrate workspace init --with-name my-workspace --with-organization my-org
# 2. Secrets erstellen
cat > secrets.poly << EOF
blocks:
- name: my-database-block
config:
database_password: "secret123"
EOF
mkdir -p artifacts/secrets
echo "kubeconfig-data" > artifacts/secrets/kubeconfig.yml
# 3. Polycrate API konfigurieren (optional aber empfohlen)
cat > ~/.polycrate/polycrate.yml << EOF
api:
enabled: true
url: https://api.polycrate.example.com
api_key: your-api-key-here
EOF
# 4. Verschlüsseln (Key wird automatisch von API geholt)
polycrate workspace encrypt
# 5. In Git committen
git add .
git commit -m "Add workspace with encrypted secrets"
git push
Developer B (Team Member)¶
# 1. Repository klonen
git clone <repo>
cd workspace
# Struktur nach Clone:
# ✅ workspace.poly
# ✅ .workspace-encrypted
# ✅ secrets.poly.age
# ✅ artifacts/secrets/*.age
# ❌ KEINE unverschlüsselten Secrets
# 2. API-Zugang konfigurieren
cat > ~/.polycrate/polycrate.yml << EOF
api:
enabled: true
url: https://api.polycrate.example.com
api_key: your-api-key-here
EOF
# 3. Workspace-Status prüfen
polycrate workspace status
# Output: Pre-commit hook automatisch installiert
# 4. Entschlüsseln (Key wird automatisch von API geholt)
polycrate workspace decrypt
# 5. Workspace ist nun nutzbar
polycrate run my-block install
Ohne API (manuelle Key-Verwaltung):
Developer A teilt den Encryption Key über einen sicheren Kanal (1Password, Signal, etc.):
# Developer B setzt den Key
export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-..."
# Entschlüsseln
polycrate workspace decrypt
Pre-Commit Hook¶
Polycrate installiert automatisch einen Pre-Commit Hook, der verhindert, dass unverschlüsselte Secrets committet werden.
Automatische Installation¶
Der Hook wird automatisch installiert wenn:
- Ein
.workspace-encryptedMarker im Workspace existiert - Ein Polycrate-Befehl ausgeführt wird
- Das Verzeichnis ein Git-Repository ist
Hook-Verhalten¶
Blockiert unverschlüsselte Secrets:
# Versuche unverschlüsselte secrets.poly zu committen
git add secrets.poly
git commit -m "Add secrets"
# Output:
# 🔒 Running Polycrate security checks...
#
# ❌ FATAL: Cannot commit - UNENCRYPTED secrets detected:
# - secrets.poly
#
# Secrets must be encrypted before committing!
#
# Fix:
# 1. Encrypt: polycrate workspace encrypt
# 2. This creates .age files (encrypted, safe to commit)
# 3. Original files are deleted automatically
# 4. Commit the .age files
Erlaubt verschlüsselte .age-Dateien:
# Verschlüssele zuerst
polycrate workspace encrypt
# Committe .age-Dateien
git add secrets.poly.age
git commit -m "Add encrypted secrets"
# Output:
# 🔒 Running Polycrate security checks...
# ✅ Security checks passed
# [main abc1234] Add encrypted secrets
Hook deaktivieren (nicht empfohlen)¶
Secret-Zugriff in Actions¶
In Ansible Playbooks¶
Secrets sind über den Workspace-Snapshot als Dateipfade verfügbar:
# Ansible Playbook - Workspace-weite Secrets
- name: Use workspace kubeconfig
shell: kubectl --kubeconfig={{ workspace.secrets['kubeconfig.yml'] }} get pods
- name: Use workspace SSH key
shell: ssh -i {{ workspace.secrets['id_rsa'] }} user@host
# Block-spezifische Secrets
- name: Use block database password
shell: |
DB_PASSWORD=$(cat {{ block.secrets['database.pwd'] }})
psql -h localhost -U user -d mydb
- name: Use block API token
uri:
url: https://api.example.com/endpoint
headers:
Authorization: "Bearer $(cat {{ block.secrets['api-token.txt'] }})"
Secret-Pfade¶
Workspace-Snapshot enthält:
workspace:
secrets:
kubeconfig.yml: /workspace/artifacts/secrets/kubeconfig.yml
id_rsa: /workspace/artifacts/secrets/id_rsa
id_rsa.pub: /workspace/artifacts/secrets/id_rsa.pub
block:
secrets:
database.pwd: /workspace/artifacts/secrets/myblock/database.pwd
api-token.txt: /workspace/artifacts/secrets/myblock/api-token.txt
Manuelle Verschlüsselung mit age CLI¶
Alle von Polycrate verschlüsselten Dateien verwenden das Standard age-Format und sind 100% kompatibel mit dem age CLI-Tool.
age CLI installieren¶
# macOS
brew install age
# Linux (Ubuntu/Debian)
sudo apt install age
# Linux (Arch)
sudo pacman -S age
Key generieren¶
Output:
# created: 2025-01-30T10:30:00Z
# public key: age1h6gqcdfckepddxa4r545w46z4n3pglj70p0defyf4mp9ja9suptsqwkk89
AGE-SECRET-KEY-1Q2LKW207HDD7MT30NQXRPSFYU0782R8V4XRHC6NJ4TLUPMLWRNPSHC83W0
Manuelle Verschlüsselung¶
# Secret Key setzen
export SECRET_KEY="AGE-SECRET-KEY-..."
# Einzelne Datei verschlüsseln
echo "$SECRET_KEY" | age --encrypt -i - secrets.poly > secrets.poly.age
# Public Key extrahieren
PUBLIC_KEY=$(echo "$SECRET_KEY" | age-keygen -y)
# Verschlüsseln mit Public Key
age --encrypt -r "$PUBLIC_KEY" secrets.poly > secrets.poly.age
Manuelle Entschlüsselung¶
# Einzelne Datei entschlüsseln
echo "$SECRET_KEY" | age --decrypt -i - secrets.poly.age > secrets.poly
# Alle .age Dateien entschlüsseln
for file in artifacts/secrets/**/*.age; do
echo "$SECRET_KEY" | age --decrypt -i - "$file" > "${file%.age}"
done
Vorteile der age-Kompatibilität:
- ✅ Notfall-Entschlüsselung ohne Polycrate
- ✅ Integration in CI/CD mit Standard-Tools
- ✅ Manuelle Schlüsselverwaltung möglich
- ✅ Kein Vendor Lock-in
.gitignore-Management¶
Polycrate aktualisiert automatisch die .gitignore um sicherzustellen, dass nur verschlüsselte Dateien committet werden.
Automatisch hinzugefügte Einträge¶
# Polycrate secrets (unencrypted)
secrets.poly # Unverschlüsselte secrets.poly
artifacts/secrets/* # Workspace-wide Secrets (Files)
!artifacts/secrets/*/ # Block-Directories erlaubt
!artifacts/secrets/*.age # Workspace .age-Files erlaubt
artifacts/secrets/*/* # Block-specific Secrets (Files)
!artifacts/secrets/*/*.age # Block .age-Files erlaubt
!.workspace-encrypted # Encryption Marker MUSS committed werden
# Legacy files (für alte Workspaces)
id_rsa # Legacy SSH Key in Root
id_rsa.pub # Legacy SSH Pub Key in Root
/kubeconfig.yml # Legacy Kubeconfig in Root
/kubeconfig.yaml # Legacy Kubeconfig in Root
Pattern-Matching-Logik¶
Ignorierte Dateien (❌):
secrets.poly- Unverschlüsselte Secrets-Configartifacts/secrets/kubeconfig.yml- Workspace-wide Fileartifacts/secrets/id_rsa- Workspace-wide Fileartifacts/secrets/myblock/database.pwd- Block-specific File
Erlaubte Dateien (✅):
secrets.poly.age- Verschlüsselte Secrets-Configartifacts/secrets/*.age- Alle verschlüsselten Workspace-wide Filesartifacts/secrets/*/*.age- Alle verschlüsselten Block-specific Files.workspace-encrypted- Encryption Marker
Sicherheits-Best-Practices¶
✅ DO¶
-
Committe .age-Dateien
-
Verschlüssele vor dem Push
-
Teile Key separat
-
1Password Shared Vault
- HashiCorp Vault
- AWS Secrets Manager
-
Polycrate API (empfohlen)
-
Verwende API für automatisches Key-Management
❌ DON'T¶
-
NIEMALS unverschlüsselte Secrets committen
-
NIEMALS Key in Git speichern
-
NIEMALS Hook umgehen
-
NIEMALS unverschlüsselt pushen
Fehlerbehandlung¶
"No workspace key found"¶
Problem: Kein Encryption Key verfügbar
Lösung:
# Option 1: API konfigurieren
cat > ~/.polycrate/polycrate.yml << EOF
api:
enabled: true
url: https://api.polycrate.example.com
api_key: your-api-key
EOF
# Option 2: Umgebungsvariable setzen
export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-..."
# Option 3: Interaktiver Prompt (automatisch)
polycrate workspace decrypt
# > Workspace-Key eingeben: ****
"FATAL: Encrypted files found"¶
Problem: Workspace enthält verschlüsselte Dateien und kann nicht geladen werden
Lösung:
# Zuerst entschlüsseln
polycrate workspace decrypt
# Dann Workspace-Operationen durchführen
polycrate run my-block install
"Key does not match encrypted file"¶
Problem: Falscher Encryption Key verwendet
Lösung:
# Prüfe API-Konfiguration
polycrate workspace status
# Oder verwende korrekten Key
export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-CORRECT-KEY-HERE"
polycrate workspace decrypt
"UNENCRYPTED secrets detected" (Pre-Commit Hook)¶
Problem: Versuch unverschlüsselte Secrets zu committen
Lösung:
# Verschlüssele zuerst
polycrate workspace encrypt
# Committe .age-Dateien
git add .
git commit -m "Update encrypted secrets"
Migration von Legacy-Workspaces¶
Wenn Ihr Workspace SSH-Keys oder Kubeconfigs direkt im Root-Verzeichnis hat, migriert Polycrate diese automatisch nach artifacts/secrets/:
Automatische Migration¶
# Legacy-Struktur (alt):
workspace/
├── id_rsa # Im Root
├── id_rsa.pub # Im Root
├── kubeconfig.yml # Im Root
# Moderne Struktur (nach Migration):
workspace/
└── artifacts/secrets/
├── id_rsa # Migriert
├── id_rsa.pub # Migriert
└── kubeconfig.yml # Migriert
Migration triggern:
Fortgeschrittene Verwendung¶
Custom Key-Generation¶
# Generiere Key mit age CLI
age-keygen -o workspace-key.txt
# Extrahiere Private Key
PRIVATE_KEY=$(grep "AGE-SECRET-KEY" workspace-key.txt)
# Verwende in Polycrate
export WORKSPACE_ENCRYPTION_KEY="$PRIVATE_KEY"
polycrate workspace encrypt
CI/CD Integration¶
# .github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install age
run: |
sudo apt-get update
sudo apt-get install -y age
- name: Decrypt workspace
env:
WORKSPACE_ENCRYPTION_KEY: ${{ secrets.WORKSPACE_ENCRYPTION_KEY }}
run: |
echo "$WORKSPACE_ENCRYPTION_KEY" | age --decrypt -i - secrets.poly.age > secrets.poly
for file in artifacts/secrets/**/*.age; do
echo "$WORKSPACE_ENCRYPTION_KEY" | age --decrypt -i - "$file" > "${file%.age}"
done
- name: Deploy
run: polycrate run my-block deploy
Key-Rotation¶
# 1. Entschlüssele mit altem Key
export WORKSPACE_ENCRYPTION_KEY="$OLD_KEY"
polycrate workspace decrypt
# 2. Verschlüssele mit neuem Key
export WORKSPACE_ENCRYPTION_KEY="$NEW_KEY"
polycrate workspace encrypt
# 3. Committe
git add .
git commit -m "Rotate encryption key"
git push
Siehe auch¶
- Workspaces - Workspace-Grundlagen
- CLI-Referenz - Vollständige CLI-Dokumentation
- Best Practices - Best Practices für Polycrate
- Konfiguration - Workspace-Konfiguration
- age-encryption.org - age Verschlüsselungstool