Как использовать SOPS c Age encryption

Используйте SOPS с шифрованием Age для защиты секретов внутри репозитория git.

Установите утилиту шифрования

Установите age — простую, современную и безопасную утилиту шифрования.

Загрузите последнюю версию.

$ curl --silent --location --remote-name https://github.com/FiloSottile/age/releases/download/v1.1.1/age-v1.1.1-linux-amd64.tar.gz

Просмотрите содержимое архива.

$ tar --list --gzip --file age-v1.1.1-linux-amd64.tar.gz
age/
age/age
age/age-keygen
age/LICENSE

Извлеките двоичные файлы.

$ sudo tar --extract --gzip --file age-v1.1.1-linux-amd64.tar.gz --strip-components 1 --directory /usr/local/bin age/age age/age-keygen

Проверьте версию приложения.

$ age --version
v1.1.1

Установите менеджер секретов

Загрузите последние версии sops — простую и гибкую утилиту для управления секретами.

$ curl --silent --location --remote-name https://github.com/getsops/sops/releases/download/v3.8.1/sops-v3.8.1.linux.amd64

Установите приложение.

$ sudo install --owner root --group root --mode 555 sops-v3.8.1.linux.amd64 /usr/local/bin/sops

Проверьте версию приложения.

$ sops --version
sops 3.8.1 (latest)

Создание ключей шифрования

Создайте ключи.

$ age-keygen -o age-key-a.txt
Public key: age1nd2t2ndwkdszt7c6gw7npfa0khxfk8ql0vphz5qur69pehu8sycq6ug0c7

$ cat age-key-a.txt
# created: 2024-03-17T16:47:09Z
# public key: age1nd2t2ndwkdszt7c6gw7npfa0khxfk8ql0vphz5qur69pehu8sycq6ug0c7
AGE-SECRET-KEY-15S5H3ARAJE6392T5LD8NLNY5GDEGE3NF4QE7LH3F9WJGR8MSCGUQPCZ2ZN

$ age-keygen -o age-key-b.txt
Public key: age1vyumxy4tpxmh7xa3k9tenf6ezhkq0dm508qy66hukx36z9ydgcps8k30d4

$ cat age-key-b.txt
# created: 2024-03-17T16:47:20Z
# public key: age1vyumxy4tpxmh7xa3k9tenf6ezhkq0dm508qy66hukx36z9ydgcps8k30d4
AGE-SECRET-KEY-1458XV43FWUPVYAM7DEN2J5N9XEZNYCREJQL44ZY4GAJMJQX3YQFSWPASKZ

Защитите эти ключи.

Добавляем доверенные ключи

Для того чтобы зашифровать секрет для нескольких ключей нужно создать файл содержащий все публичные ключи Age/

echo 'age1ls2ftwdzyu0ptdqe8mysde7mzwjdagqvvepr3hk2ysduhlz47enqxtymfh,age17aeun7qfjz470e4k4r3650h6hxdghtnh3z73llczzzzhvhlal44q4h8lsq' > public-age-keys.txt

Создаем переменную с доверенными ключами

export SOPS_AGE_RECIPIENTS=$(<public-age-keys.txt)

И теперь можем зашифровать файл с чувствительными данными.

sops --encrypt --age ${SOPS_AGE_RECIPIENTS} secret.json > secret.json.enc

Оператор секретов

Определите версию Kubernetes.

$ kubectl version
Client Version: v1.29.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.29.2

Определите значения по умолчанию для sops-secrets-operator. Тег образа зависит от используемой версии программного обеспечения, ознакомьтесь с файлом readme в репозитории GitHub, чтобы узнать больше. Другими наиболее важными частями являются secretsAsFiles (какой секрет использовать) и extraEnv (какой ключ использовать).

$ tee sops-values.yaml <<'EOF'
# Default values for sops-secrets-operator.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

# https://github.com/norwoodj/helm-docs and https://pre-commit.com/
# are used to generate documentation automaticaly

# -- Deployment replica count - should not be modified
replicaCount: 1

# UPDATE_HERE
image:
  # -- Operator image name
  repository: isindir/sops-secrets-operator
  # -- Operator image tag
  tag: 0.12.4
  # -- Operator image pull policy
  pullPolicy: Always

# UPDATE_HERE
initImage:
  # -- Init container image name
  repository: ubuntu
  # -- Init container image tag
  tag: noble-20240225
  # -- Init container image pull policy
  pullPolicy: Always

# -- Secrets to pull image from private docker repository
imagePullSecrets: []
# -- Overrides auto-generated short resource name
nameOverride: ""
# -- Overrides auto-generated long resource name
fullnameOverride: ""

# -- Annotations to be added to operator pod (can be used with kiam or kube2iam)
podAnnotations: {}

serviceAccount:
  # -- Annotations to be added to the service account
  annotations: {}

# -- Requeue failed reconciliation in minutes (min 1). (default 5)
requeueAfter: 5

# -- Paths to a kubeconfig. Only required if out-of-cluster.
kubeconfig:
  enabled: false
  path:

# -- Logging configuration section suggested values
# Development Mode (encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn).
# Production Mode (encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default)
logging:
  # -- Zap Development Mode enabled
  development: false
  # -- Zap log encoding (one of 'json' or 'console')
  encoder: json
  # -- Zap Level to configure the verbosity of logging. Can be one of 'debug', 'info', 'error', or any integer value > 0 which corresponds to custom debug levels of increasing verbosity
  level: info
  # -- Zap Level at and above which stacktraces are captured (one of 'info', 'error').
  stacktraceLevel: error
  # -- Zap time encoding (one of 'epoch', 'millis', 'nano', 'iso8601', 'rfc3339' or 'rfc3339nano'). Defaults to 'epoch'.
  timeEncoding: iso8601

healthProbes:
  # -- The address the probe endpoint binds to. (default ":8081")
  port: 8081
  # -- Liveness probe configuration
  liveness:
    initialDelaySeconds: 15
    periodSeconds: 20
  # -- Readiness probe configuration
  readiness:
    initialDelaySeconds: 5
    periodSeconds: 10

# -- GPG configuration section
gpg:
  # -- If `true` GCP secret will be created from provided value and mounted as environment variable
  enabled: false
  # -- Name of the secret to create - will override default secret name if specified
  secret1: gpg1
  # -- Name of the secret to create - will override default secret name if specified
  secret2: gpg2

# -- GCP KMS configuration section
gcp:
  # -- Node labels for operator pod assignment
  enabled: false
  # -- Name of the secret to create - will override default secret name if specified
  svcAccSecretCustomName: ''
  # -- If `gcp.enabled` is `true`, this value must be specified as GCP service account secret json payload
  svcAccSecret: ''
  # -- Name of a pre-existing secret containing GCP service account secret json payload
  existingSecretName: ''


# -- Azure KeyVault configuration section
azure:
  # Specify credentials here or use existingSecretName below to use a pre-configred secret

  # -- if true Azure KeyVault will be used
  enabled: false
  # -- TenantID of Azure Service principal to use
  tenantId: ''
  # -- ClientID (Application ID) of Azure Service Principal to use
  clientId: ''
  # -- Client Secret of Azure Service Principal
  clientSecret: ''
  # Pre-existing secret must contain the keys tenantId, clientId and clientSecret with the appropriate values
  # -- Name of a pre-existing secret containing Azure Service Principal Credentials (ClientID, ClientSecret, TenantID)
  existingSecretName: ''

# -- A list of additional environment variables
extraEnv:
  - name: SOPS_AGE_KEY_FILE
    value: /etc/sops-age-keys/age-key.txt
#- name: AWS_SDK_LOAD_CONFIG
#  value: "1"

# -- configure custom secrets to be used as environment variables at runtime, see values.yaml
secretsAsEnvVars: []
#- name: SECRET_GREETING
#  secretName: my-secret-greeting
#  secretKey: greeting

# -- configure custom secrets to be mounted at runtime, see values.yaml
secretsAsFiles:
  - mountPath: /etc/sops-age-keys
    name: age-keys
    secretName: sops-age-key-file
  # Repeat for as many keys as you have
# All files within secret will be mounted in "/etc/foo" - same as 1st example in k8s documentation
# all secrets will be mounted as readonly
#- name: foo
#  mountPath: "/etc/foo"
#  secretName: mysecret

# -- Operator container resources
resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 500m
  #   memory: 128Mi
  # requests:
  #   cpu: 10m
  #   memory: 64Mi

# -- Node selector to use for pod configuration
nodeSelector: {}

securityContext:
  # -- Enable securityContext
  enabled: false
  # -- UID to run as
  runAsUser: 13001
  # -- GID to run as
  runAsGroup: 13001
  # -- Enable kubelet validation for using root user to run container
  runAsNonRoot: true
  # -- fs group
  fsGroup: 13001
  # -- seccompProfile.type
  seccompProfileType: RuntimeDefault
  # -- if seccompProfile.type is set to Localhost, set localhostProfile to value of seccompProfileName (user must specify value)
  seccompProfileName: ""
  # -- container/initContainer
  container:
    # -- enables securityContext capabilities feature in containers
    enabled: false
    # -- capabilities
    capabilities:
      drop:
        - all
      add:
        - NET_BIND_SERVICE

# -- Tolerations to be applied to operator pod
tolerations: []

# -- Node affinity for pod assignment
affinity: {}

rbac:
  # -- Create and use RBAC resources
  enabled: true

metrics:
  # -- Enable prometheus metrics
  enabled: false
EOF

Добавляем репозиторий sops-secrets-operator

$ helm3 repo add sops https://isindir.github.io/sops-secrets-operator/
"sops" has been added to your repositories

Установка оператора

$ helm3 upgrade --install sops sops/sops-secrets-operator --create-namespace --namespace sops --values sops-values.yaml
Release "sops" does not exist. Installing it now.
NAME: sops
LAST DEPLOYED: Sun Mar 17 20:40:47 2024
NAMESPACE: sops
STATUS: deployed
REVISION: 1
TEST SUITE: None

Он пока не будет работать, так как мы должны сначала создать секрет, который включает в себя ранее сгенерированные ключи.

$ kubectl get --namespace sops deployments
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
sops-sops-secrets-operator   0/1     1            0           10m

Создайте секрет, используя один или несколько ключей.

$ kubectl create --namespace sops secret generic sops-age-key-file --from-file=age-key.txt=<(cat age-key-a.txt age-key-b.txt)
secret/sops-age-key-file created

Посмотрим созданный секрет.

$ kubectl get --namespace sops secret sops-age-key-file -o yaml
apiVersion: v1
data:
  age-key.txt: IyBjcmVhdGVkOiAyMDI0LTAzLTE3VDE2OjQ3OjA5WgojIHB1YmxpYyBrZXk6IGFnZTFuZDJ0Mm5kd2tkc3p0N2M2Z3c3bnBmYTBraHhmazhxbDB2cGh6NXF1cjY5cGVodThzeWNxNnVnMGM3CkFHRS1TRUNSRVQtS0VZLTE1UzVIM0FSQUpFNjM5MlQ1TEQ4TkxOWTVHREVHRTNORjRRRTdMSDNGOVdKR1I4TVNDR1VRUENaMlpOCiMgY3JlYXRlZDogMjAyNC0wMy0xN1QxNjo0NzoyMFoKIyBwdWJsaWMga2V5OiBhZ2Uxdnl1bXh5NHRweG1oN3hhM2s5dGVuZjZlemhrcTBkbTUwOHF5NjZodWt4MzZ6OXlkZ2NwczhrMzBkNApBR0UtU0VDUkVULUtFWS0xNDU4WFY0M0ZXVVBWWUFNN0RFTjJKNU45WEVaTllDUkVKUUw0NFpZNEdBSk1KUVgzWVFGU1dQQVNLWgo=
kind: Secret
metadata:
  creationTimestamp: "2024-03-17T21:00:05Z"
  name: sops-age-key-file
  namespace: sops
  resourceVersion: "133989"
  uid: a76654cf-d6ae-42bd-a785-d3035b48d691
type: Opaque

Расшифруйте его содержимое.

$ kubectl get --namespace sops secret sops-age-key-file -o go-template='{{ range $key, $value := .data }}{{ $key }}{{ ": " }}{{ $value | base64decode }}{{ "\n" }}{{ end }}'
age-key.txt: # created: 2024-03-17T16:47:09Z
# public key: age1nd2t2ndwkdszt7c6gw7npfa0khxfk8ql0vphz5qur69pehu8sycq6ug0c7
AGE-SECRET-KEY-15S5H3ARAJE6392T5LD8NLNY5GDEGE3NF4QE7LH3F9WJGR8MSCGUQPCZ2ZN
# created: 2024-03-17T16:47:20Z
# public key: age1vyumxy4tpxmh7xa3k9tenf6ezhkq0dm508qy66hukx36z9ydgcps8k30d4
AGE-SECRET-KEY-1458XV43FWUPVYAM7DEN2J5N9XEZNYCREJQL44ZY4GAJMJQX3YQFSWPASKZ

Подождите, пока sops-оператор не будет готово к использованию.

$ kubectl wait --namespace sops deployment  --for=condition=available --selector=app.kubernetes.io/name=sops-secrets-operator --timeout=120s
deployment.apps/sops-sops-secrets-operator condition met

Теперь sops-оператор работает.

Создавайте секреты с помощью шаблонов

$ tee sopssecret-general-1.yml <<EOF
apiVersion: isindir.github.com/v1alpha3
kind: SopsSecret
metadata:
  name: sopssecret-general-1
  namespace: default
spec:
  suspend: false
  secretTemplates:
    - name: secret-index-1
      stringData:
        index: "Hello world (secret 1)!!!"
EOF
$ sops --age age1nd2t2ndwkdszt7c6gw7npfa0khxfk8ql0vphz5qur69pehu8sycq6ug0c7 --encrypted-suffix='Templates' --encrypt sopssecret-general-1.yml > sopssecret-general-1.enc.yml
$ cat sopssecret-general-1.enc.yml
apiVersion: isindir.github.com/v1alpha3
kind: SopsSecret
metadata:
    name: sopssecret-general-1
    namespace: default
spec:
    suspend: false
    secretTemplates:
        - name: ENC[AES256_GCM,data:A9NHhUbkei9vuEUUlzw=,iv:CoKDgKUwD1+xTyaZqed8zn+3fNZ38V0Qn/ZdOL6JTn8=,tag:+W1z0fAt0pGJtrI0jgpcFw==,type:str]
          stringData:
            index: ENC[AES256_GCM,data:L01jnkjyLcLLKnNqTrHQvkOfzzu+spJHyQ==,iv:vM1nxLm4v0w/cTW2zaWyI2utsN6YemGk/8USh2b127I=,tag:2KJltWvYSHtMHBWpBpD7gg==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    hc_vault: []
    age:
        - recipient: age1nd2t2ndwkdszt7c6gw7npfa0khxfk8ql0vphz5qur69pehu8sycq6ug0c7
          enc: |
            -----BEGIN AGE ENCRYPTED FILE-----
            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLUGhxY1Q2eUhzSjN1dGdS
            OFpjRElEYzdGRGt5VnVXbElRTnJSSnYxSVFnCk1UanM5UFRGekNhOWFOL2I2ZTk3
            MFhlMWlkbkJ3V2ZrRktBSE1xU1NlUlUKLS0tIEs5UE1ZODBHVXZPbFhTbGpqblRo
            T2tBb3VsUVpsdTAvSUlRbjZSbThsQTQK9jhi1GrnnQwYYAK6HN8/hCRm1ln81PGl
            RDFOt21tUpo1uKIt8twY3V5e1KhEWraGeAINtNW0K9010BsdFm7BUA==
            -----END AGE ENCRYPTED FILE-----
    lastmodified: "2024-03-17T21:28:56Z"
    mac: ENC[AES256_GCM,data:2C5aP0oSZAUSu4lpa7gvX9YKb+/22ZlaYjXmzVStRS9Uv/uEWxA/NJlP8Mu7fBWdkNEtbAd78/Y4THs2qIo9p2nuUDeQ7RQlMHh5icpScaCNx/amIpX6P3VQO7fNcl3aYvdC7Su5N4xdqqnRqe8cThTHgrKBX8xhO27bm1n0lXw=,iv:QPdcHQj4GW1vKQ2i1hYgtDykvqlr4Scll1+Xg4h9ib0=,tag:kJFNMur1FrqggpkxxT1xWQ==,type:str]
    pgp: []
    encrypted_suffix: Templates
    version: 3.8.1

Создайте и зашифруйте второй секретный шаблон.

$ tee sopssecret-general-2.yml <<EOF
apiVersion: isindir.github.com/v1alpha3
kind: SopsSecret
metadata:
  name: sopssecret-general-2
  namespace: default
spec:
  suspend: false
  secretTemplates:
    - name: secret-index-2
      stringData:
        index: "Hello world (secret 2)!!!"
EOF
$ sops --age age1vyumxy4tpxmh7xa3k9tenf6ezhkq0dm508qy66hukx36z9ydgcps8k30d4 --encrypted-suffix='Templates' --encrypt sopssecret-general-2.yml > sopssecret-general-2.enc.yml
$ cat sopssecret-general-2.enc.yml
apiVersion: isindir.github.com/v1alpha3
kind: SopsSecret
metadata:
    name: sopssecret-general-2
    namespace: default
spec:
    suspend: false
    secretTemplates:
        - name: ENC[AES256_GCM,data:0yRcsB8rjm2pXIVYXsE=,iv:wqg1tO1uCVQYgnpSo3ijFw6E8lvX/xHCQVooWoGn6No=,tag:UrjnJZXdcbeDMTa9AaAZxg==,type:str]
          stringData:
            index: ENC[AES256_GCM,data:Ns7KDI+agA2+c5TGoLp8VV/OlmTY8C+C/A==,iv:H4oqTU1fGVUf6HI6364NvegwPdHD8xoqvQcAbrLZ1pw=,tag:EhelBnsjODBEmQVXs35WPg==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    hc_vault: []
    age:
        - recipient: age1vyumxy4tpxmh7xa3k9tenf6ezhkq0dm508qy66hukx36z9ydgcps8k30d4
          enc: |
            -----BEGIN AGE ENCRYPTED FILE-----
            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnYmRnVWVPdnRWdzNsUFk0
            Wk04NWF1ZU1nZWI2STEwSDdNQ0tRQStkaGlNCnZvZmkvWkxGSERvckFYcFVUMHFp
            ZUtFWkNzUXVhSFFZTkRONVVvdlU3ck0KLS0tIFlHeXlyY0lDZUZEbFc0WDJZNG9F
            WERsd1V1dUdtM0wrcUVCQ3Qwb1BFaFUK0++rRSLfz4J5wJDFbL0BDlI3P/kwlQ7A
            /AAp/ocfCVKjCg9MD/4ariRtGk5ALaIoFypkOXIByoj3lQ/Nc8TP3g==
            -----END AGE ENCRYPTED FILE-----
    lastmodified: "2024-03-17T21:32:00Z"
    mac: ENC[AES256_GCM,data:FEtKZaZMYboslvl/9jterThtY9srcp3XnNGbBo2EiceR//UK/KH9fRI2Zz2Ek7+eKLwHUYsPuKy565jsKl7t+GUVCaGlsROVzkx1h5duPnEYinXvCvzYacvQa1ztW/YGpxYUYwpPUVns0bYt48wvWu0BGpeDqunx0g0y0xUlQQk=,iv:CQDZQTTNiSrtGEjXnm9SDmTpHoaesoBRSUOtgTyCshc=,tag:BZcUUA/fFq/Uc1E5SjA2sA==,type:str]
    pgp: []
    encrypted_suffix: Templates
    version: 3.8.1
Применим манифесты в кубер.
$ kubectl apply -f sopssecret-general-1.enc.yml,sopssecret-general-2.enc.yml
sopssecret.isindir.github.com/sopssecret-general-1 created
sopssecret.isindir.github.com/sopssecret-general-2 created

Проверьте созданные ресурсы.

$ kubectl get sopssecrets
NAME                   STATUS
sopssecret-general-1   Healthy
sopssecret-general-2   Healthy

Проверяйте секреты, созданные на основе шаблонов.

$ kubectl get secrets
NAME             TYPE     DATA   AGE
secret-index-1   Opaque   1      26s
secret-index-2   Opaque   1      26s
$ kubectl get secret secret-index-1 secret-index-2 -o go-template='{{ range .items -}}{{ range $key, $value := .data }}{{ $key }}{{ ": " }}{{ $value | base64decode }}{{ "\n" }}{{ end }}{{ end }}'
index: Hello world (secret 1)!!!
index: Hello world (secret 2)!!!

Выполните простой тест

Создайте примеры deployments

$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: octopus-httpd
  name: httpd-octopus
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: octopus-httpd
  template:
    metadata:
      labels:
        app: octopus-httpd
    spec:
      containers:
      - image: httpd:latest
        name: octopus-httpd
        ports:
        - name: http
          protocol: TCP
          containerPort: 80 
        volumeMounts:
        - name: html-volume
          mountPath: "/usr/local/apache2/htdocs/index.html"
          subPath: "index.html"
      volumes:
      - name: html-volume
        secret:
          secretName: secret-index-1
          items:
          - key: index
            path: index.html                      
---
apiVersion: v1
kind: Service
metadata:
  name: octopus-service
spec:
  type: ClusterIP
  ports:
    - name: http
      port: 80
      protocol: TCP
  selector:
    app: octopus-httpd        
EOF
deployment.apps/httpd-octopus created
service/octopus-service created
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: squid-httpd
  name: httpd-squid
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: squid-httpd
  template:
    metadata:
      labels:
        app: squid-httpd
    spec:
      containers:
      - image: httpd:latest
        name: squid-httpd
        ports:
        - name: http
          protocol: TCP
          containerPort: 80 
        volumeMounts:
        - name: html-volume
          mountPath: "/usr/local/apache2/htdocs/index.html"
          subPath: "index.html"
      volumes:
      - name: html-volume
        secret:
          secretName: secret-index-2
          items:
          - key: index
            path: index.html                      
---
apiVersion: v1
kind: Service
metadata:
  name: squid-service
spec:
  type: ClusterIP
  ports:
    - name: http
      port: 80
      protocol: TCP
  selector:
    app: squid-httpd        
EOF
deployment.apps/httpd-squid created
service/squid-service created

Проверьте созданные ресурсы.

$ kubectl get deployments
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
httpd-octopus   1/1     1            1           59s
httpd-squid     1/1     1            1           38s
$ kubectl get services
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes        ClusterIP   10.152.183.1             443/TCP   97m
octopus-service   ClusterIP   10.152.183.152           80/TCP    6m11s
squid-service     ClusterIP   10.152.183.138           80/TCP    5m31s
Выполните тест.
$ curl 10.152.183.152
Hello world (secret 1)!!!
$ curl 10.152.183.138
Hello world (secret 2)!!!

Дополнительные примечания

Вы сможете обновить helm-chart

$ helm3 upgrade --reuse-values -f sops-values.yaml -n default sops sops/sops-secrets-operator
Release "sops" has been upgraded. Happy Helming!
NAME: sops
LAST DEPLOYED: Sun Mar 17 12:18:41 2024
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None

В редких случаях вы увидите аналогичную ошибку при попытке перезаписать существующий секрет

$ kubectl get sopssecrets
NAME                   STATUS
sopssecret-general-1   Healthy
sopssecret-general-2   Child secret is not owned by controller error
$ kubectl get secrets
NAME           TYPE     DATA   AGE
secret-index   Opaque   1      3m34s

Чтобы поменять ключи местами, просто добавьте новый и повторно зашифруйте SopsSecrets.

Источник-1: https://sleeplessbeastie.eu/2024/03/20/how-to-utilize-sops-with-age-encryption/

Источник-2: https://devops.datenkollektiv.de/using-sops-with-age-and-git-like-a-pro.html

Was this helpful?

0 / 0