Skip to main content

SOPS Encryption

Purpose: For platform engineers, shows how to encrypt/decrypt with SOPS Age keys and use opencenter cluster sync-secrets.

Task Summary

Most secret management in openCenter is handled by the CLI (sync-secrets). This guide covers the manual SOPS workflow for cases where you need to encrypt a new secret file, decrypt for debugging, or edit an existing encrypted file in place.

Backend Operation Support

openCenter supports two secrets backends: SOPS and Barbican. They differ in which CLI operations they support because of a fundamental design difference — SOPS operates on encrypted files, while Barbican is a key-value secret store.

OperationSOPSBarbican
secrets encrypt
secrets decrypt
secrets status
secrets sync
secrets validate
secrets list
secrets get
secrets set
secrets delete
secrets describe
secrets login

SOPS manages secrets as whole encrypted YAML files, not individual key-value pairs. There is no concept of "get one secret by name" or "delete one secret" — you encrypt or decrypt entire files. The get, set, delete, and describe operations are only available with the Barbican backend.

If you attempt a CRUD operation (get, set, delete, describe) with the SOPS backend configured, the CLI returns an error with guidance pointing to the file-level alternatives:

$ opencenter secrets get my-secret
Error: SOPS backend does not support individual secret get operations.

SOPS manages secrets as encrypted YAML files, not individual key-value pairs.
To work with SOPS secrets:
opencenter secrets encrypt Encrypt YAML files
opencenter secrets decrypt Decrypt YAML files
opencenter secrets status Show encryption status

Documentation: https://docs.opencenter.cloud/secrets/sops-encryption

To manage individual secret values with SOPS, edit the plaintext config file and run opencenter secrets sync to re-encrypt. See Secrets Model for the full flow.

Prerequisites

  • sops CLI installed (v3.8+)
  • age CLI installed (for key generation, if needed)
  • The cluster's Age public key (found in .sops.yaml or secrets/age/)
  • Access to the customer GitOps repository

Encrypt a New Secret

Step 1: Create the plaintext manifest

Write a standard Kubernetes Secret manifest:

# secret.yaml (plaintext — do NOT commit this)
apiVersion: v1
kind: Secret
metadata:
name: my-app-credentials
namespace: my-app
type: Opaque
stringData:
username: admin
password: "s3cret-value"

Step 2: Encrypt with SOPS

If a .sops.yaml file exists in the directory (or a parent directory), SOPS picks up the creation rules automatically:

sops --encrypt --in-place secret.yaml

To encrypt with an explicit Age recipient:

sops --encrypt --age age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--encrypted-regex '^(data|stringData)$' \
--in-place secret.yaml

The --encrypted-regex flag ensures only data and stringData fields are encrypted. Metadata stays in plaintext so FluxCD and Kustomize can process the file.

Step 3: Verify encryption

Open the file and confirm values are replaced with ENC[AES256_GCM,...] blocks:

head -20 secret.yaml

Expected output:

apiVersion: v1
kind: Secret
metadata:
name: my-app-credentials
namespace: my-app
type: Opaque
stringData:
username: ENC[AES256_GCM,data:...,type:str]
password: ENC[AES256_GCM,data:...,type:str]
sops:
age:
- recipient: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
...

Step 4: Commit the encrypted file

git add secret.yaml
git commit -m "Add encrypted credentials for my-app"

Decrypt for Debugging

To view decrypted contents without modifying the file:

export SOPS_AGE_KEY_FILE=secrets/age/<cluster>_keys.txt
sops --decrypt secret.yaml

This prints the plaintext to stdout. Do not redirect to a file in the repository.

Edit an Encrypted File In Place

SOPS can open an encrypted file in your editor, decrypt it for editing, and re-encrypt on save:

export SOPS_AGE_KEY_FILE=secrets/age/<cluster>_keys.txt
sops secret.yaml

This opens the decrypted content in $EDITOR. When you save and close, SOPS re-encrypts the file automatically.

Use the CLI for Bulk Operations

For standard secret management, prefer the CLI over manual SOPS commands:

# Sync all secrets from config to encrypted manifests
opencenter cluster sync-secrets <cluster-name>

# Validate that all encrypted files decrypt correctly
opencenter cluster validate-secrets <cluster-name>

sync-secrets reads the plaintext config, generates Secret manifests, encrypts them with the correct .sops.yaml rules, and writes them to the proper overlay directories.

The .sops.yaml Configuration

Each customer repository contains .sops.yaml files that define encryption rules per directory. SOPS walks up the directory tree to find the nearest .sops.yaml:

creation_rules:
- path_regex: applications/overlays/k8s-sandbox/.*
encrypted_regex: "^(data|stringData)$"
age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

See SOPS Configuration Reference for the full schema.

Troubleshooting

"no matching creation rule" error: SOPS cannot find a .sops.yaml with a path_regex matching the file's path. Check that the file is in a directory covered by a creation rule, or pass --age explicitly.

"failed to decrypt" error: The Age private key does not match the recipient in the encrypted file. Verify SOPS_AGE_KEY_FILE points to the correct key file for this cluster.

Encrypted file has no sops: metadata block: The file was not encrypted. Re-run sops --encrypt --in-place <file>.