Skip to content

Commit

Permalink
Decrypt SOPS secrets for diff
Browse files Browse the repository at this point in the history
Signed-off-by: Boris Kreitchman <[email protected]>
  • Loading branch information
bkreitch committed Feb 19, 2025
1 parent 3226043 commit 8dce48a
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 9 deletions.
1 change: 1 addition & 0 deletions cmd/flux/build_kustomization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func setup(t *testing.T, tmpl map[string]string) {
t.Helper()
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-source.yaml", tmpl, t)
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-kustomization.yaml", tmpl, t)
testEnv.CreateObjectFile("./testdata/build-kustomization/sops-age.yaml", tmpl, t)
}

func TestBuildKustomization(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions cmd/flux/diff_kustomization.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type diffKsFlags struct {
progressBar bool
strictSubst bool
recursive bool
decryptSecrets bool
localSources map[string]string
}

Expand All @@ -74,6 +75,7 @@ func init() {
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
diffKsCmd.Flags().BoolVarP(&diffKsArgs.recursive, "recursive", "r", false, "Recursively diff Kustomizations")
diffKsCmd.Flags().BoolVar(&diffKsArgs.decryptSecrets, "decrypt-secrets", false, "Decrypt SOPS-encrypted secrets for comparison")
diffKsCmd.Flags().StringToStringVar(&diffKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
diffCmd.AddCommand(diffKsCmd)
}
Expand Down Expand Up @@ -111,6 +113,7 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
build.WithIgnore(diffKsArgs.ignorePaths),
build.WithStrictSubstitute(diffKsArgs.strictSubst),
build.WithRecursive(diffKsArgs.recursive),
build.WithDecryptSecrets(diffKsArgs.decryptSecrets),
build.WithLocalSources(diffKsArgs.localSources),
build.WithSingleKustomization(),
)
Expand Down
6 changes: 6 additions & 0 deletions cmd/flux/diff_kustomization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ func TestDiffKustomization(t *testing.T) {
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drifted-value-sops-secret.golden"),
},
{
name: "diff with a drifted value in decrypted sops secret object",
args: "diff kustomization podinfo --path ./testdata/build-kustomization/decrypt-secret --progress-bar=false --decrypt-secrets",
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-decryption.golden"),
},
{
name: "diff with a sops dockerconfigjson secret object",
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: v1
kind: Secret
metadata:
name: podinfo-token-77t89m9b67
stringData:
token: ENC[AES256_GCM,data:ut7THDa7SJMTIn26orb2,iv:jBqKk4f8jzOZLpoH7pMnryHRAwwvjaycKwBryEBO3oQ=,tag:193UGSrkhQJzs4pDg5u2mQ==,type:str]
type: Opaque
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1yqval9atdcnzjwhmutcjwdukfe5pk9tsa3lqya90u08grp03zgyss93knx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxeGdXSVAyMGUzSFpwRGNF
bUV5bU9scVJsRUVwbERFYWVjSVpJNFlYREJRCm5xaGxzZGRic0ZwY3hJSmJOcWk3
UmYzUDNIU29zd3orYlFlemNGUDhWZVEKLS0tIFJCcEsrdmlZcHBFWFE3SUlCaUNZ
ZkJuMm83a0VNODdXMkxUeDRmemJ2blkKebY+krevnla3Rxhrm3T4mmao8NUishwl
W4sV4fM2m5gjpiz72MVPjUrakqo9lA9ZLUkSue95YzFe09o7uqglRQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-16T20:34:53Z"
mac: ENC[AES256_GCM,data:C6Sv7iAoMztDGMDTYEW5KFUGSdey6O9zLzNdaEHxQL1oTrQB/hSBOjA4jaEBHovdCL/58w9jDTq8G30IGqUEFEu4HM0YUrSDA1gdTrbtvOfza0hQC8CtmCBWgol3tsWBwcLAeFOlE95perdvKkJx10t/r8yb8biCpLtJcxa/WZE=,iv:2CswtWAATMPZ7BHzWSUNhvT9xfmSSGPdOMvG1jHi3Nk=,tag:FZeCX+EuAlsOGaZbErpfJQ==,type:str]
pgp: []
encrypted_regex: ^(data|stringData)$
version: 3.9.1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ spec:
kind: GitRepository
name: podinfo
targetNamespace: default
decryption:
provider: sops
secretRef:
name: sops-age
postBuild:
substitute:
cluster_env: "prod"
Expand Down
10 changes: 10 additions & 0 deletions cmd/flux/testdata/build-kustomization/sops-age.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: sops-age
namespace: {{ .fluxns }}
type: Opaque
stringData:
identity.agekey: |
# public key: age1yqval9atdcnzjwhmutcjwdukfe5pk9tsa3lqya90u08grp03zgyss93knx
AGE-SECRET-KEY-1JYSQLQ4QM6GZHDF4F5JLA3HZD2DFJFCMAA2ASCN2USTC02KC4V6SSZNLA7
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
► Secret/default/podinfo-token-77t89m9b67 drifted

data.token
± value change
- *** (before)
+ *** (after)

57 changes: 48 additions & 9 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml"

kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
"github.com/fluxcd/kustomize-controller/decryptor"
"github.com/fluxcd/pkg/kustomize"
runclient "github.com/fluxcd/pkg/runtime/client"
ssautil "github.com/fluxcd/pkg/ssa/utils"
Expand Down Expand Up @@ -77,15 +78,16 @@ type Builder struct {
kustomizationFile string
ignore []string
// mu is used to synchronize access to the kustomization file
mu sync.Mutex
action kustomize.Action
kustomization *kustomizev1.Kustomization
timeout time.Duration
spinner *yacspin.Spinner
dryRun bool
strictSubst bool
recursive bool
localSources map[string]string
mu sync.Mutex
action kustomize.Action
kustomization *kustomizev1.Kustomization
timeout time.Duration
spinner *yacspin.Spinner
dryRun bool
strictSubst bool
recursive bool
decryptSecrets bool
localSources map[string]string
// diff needs to handle kustomizations one by one
singleKustomization bool
}
Expand Down Expand Up @@ -190,6 +192,14 @@ func WithRecursive(recursive bool) BuilderOptionFunc {
}
}

// WithDecryptSecrets sets the decrypt secrets field
func WithDecryptSecrets(decryptSecrets bool) BuilderOptionFunc {
return func(b *Builder) error {
b.decryptSecrets = decryptSecrets
return nil
}
}

// WithLocalSources sets the local sources field
func WithLocalSources(localSources map[string]string) BuilderOptionFunc {
return func(b *Builder) error {
Expand Down Expand Up @@ -514,7 +524,36 @@ func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomizatio
return nil, fmt.Errorf("kustomize build failed: %w", err)
}

var dec *decryptor.Decryptor
var cleanup func()
if b.decryptSecrets {
dec, cleanup, err = decryptor.NewTempDecryptor(b.resourcesPath, b.client, b.kustomization)
if err != nil {
return nil, err
}
defer cleanup()

// Import decryption keys
if err := dec.ImportKeys(ctx); err != nil {
return nil, err
}
}

for _, res := range m.Resources() {
if res.GetKind() == "Secret" && b.decryptSecrets {
outRes, err := dec.DecryptResource(res)
if err != nil {
return nil, fmt.Errorf("decryption failed for '%s': %w", res.GetName(), err)
}

if outRes != nil {
_, err = m.Replace(res)
if err != nil {
return nil, err
}
}
}

// run variable substitutions
if kustomization.Spec.PostBuild != nil {
data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&kustomization)
Expand Down
1 change: 1 addition & 0 deletions internal/build/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ func (b *Builder) kustomizationDiff(kustomization *kustomizev1.Kustomization) (s
WithIgnore(b.ignore),
WithStrictSubstitute(b.strictSubst),
WithRecursive(b.recursive),
WithDecryptSecrets(b.decryptSecrets),
WithLocalSources(b.localSources),
WithSingleKustomization(),
)
Expand Down

0 comments on commit 8dce48a

Please sign in to comment.