fluxcd / kustomize-controller

The GitOps Toolkit Kustomize reconciler
https://fluxcd.io
Apache License 2.0
255 stars 182 forks source link

Wrong decrypt SOPS files #421

Closed aivanov-citc closed 3 years ago

aivanov-citc commented 3 years ago

Hey! When switching from version flux 0.13.4 to 0.16.2, files encrypted with SOPs became incorrectly decrypted.

There is file realm.json

{
  "id": "example",
  "realm": "example",
  "notBefore": 0,
  "defaultSignatureAlgorithm": "RS256",
  "revokeRefreshToken": false,
...
}

encrypted by such command

cat realm.json | sops -e -p 565C51B96C276C5DF7C07CA782F13DCA5F7C4DF7 /dev/stdin > realm.json.encrypted
{
  "data": "ENC[AES256_GCM,data:L2g/kuDeWee+xJBF4tPMt7q ...
...
}

Kustomize secretGenerator

secretGenerator:
  - name: config-secret
    files:
    - realm.json=realm.json.encrypted

When decrypting on version flux 0.13.4, we get a correct contents of the secret

{
  "id": "example",
  "realm": "example",
  "notBefore": 0,
  "defaultSignatureAlgorithm": "RS256",
  "revokeRefreshToken": false,
...
}

on version flux 0.16.2 this is

{
  "data": "{\n  \"id\": \"example\",\n  \"realm\": \"example\",\n  \"notBefore\": 0,\n  \"defaultSignatureAlgorithm\": \"RS256\",\n  \"revokeRefreshToken\": false,\n ...
...
}

version sops - 3.7.1

stefanprodan commented 3 years ago

I tested this on my cluster and once the secret is mounted, the json is decoded correctly.

Create realm.json:

{
    "id": "example",
    "realm": "example",
    "notBefore": 0,
    "defaultSignatureAlgorithm": "RS256",
    "revokeRefreshToken": false
}

Encrypt it in-place:

sops --age=$AGEPUB --encrypt --in-place realm.json

Create a deployment that mounts the secret:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
  namespace: default
spec:
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      containers:
      - name: podinfod
        image: ghcr.io/stefanprodan/podinfo:6.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 9898
          #protocol: TCP
        volumeMounts:
          - name: secrets
            mountPath: "/secrets"
            readOnly: true
      volumes:
        - name: secrets
          secret:
            secretName: json-secret

Create a kustomization that generates the Kubernetes secret:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
resources:
  - deployment.yaml
secretGenerator:
  - name: json-secret
    files:
      - realm.json=realm.json

Create a Flux kustomization to apply the above:

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: secrets
  namespace: flux-system
spec:
  decryption:
    provider: sops
    secretRef:
      name: sops-age
  interval: 1m0s
  path: ./secrets/test
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system

After Flux reconciles the above, exec into the podinfo pod and print the json:

~ $ cat /secrets/realm.json 
{
    "id": "example",
    "realm": "example",
    "notBefore": 0,
    "defaultSignatureAlgorithm": "RS256",
    "revokeRefreshToken": false
}
stefanprodan commented 3 years ago

@aivanov-citc the issue here is that you pipe the json into sops without telling SOPS what content type is it. So sops adds the data key as it thinks you are encrypting a binary file.

As I posted above you can encrypt in-place or add --input-type=json to your command like so:

cat realm.json | sops -e --input-type=json -p 565C51B96C276C5DF7C07CA782F13DCA5F7C4DF7 /dev/stdin > realm.json.encrypted
aivanov-citc commented 3 years ago

Yes indeed. When specifying the file type, it works in version 0.16.2, but does not work in version 0.13.4. We will have to update both the flux version and reencrypt the files at the same time. Thanks.

stefanprodan commented 3 years ago

@aivanov-citc please consider upgrading to latest Flux, see here the upgrade guide: https://github.com/fluxcd/flux2/discussions/1916