diff --git a/README.md b/README.md index 3a39b61..1dab70d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ in this repository (in that order) are good starting points.* - [with file Attribute value](#with-file-attribute-value) - [with directory Attribute value](#with-directory-attribute-value) - [Order Workaround](#order-workaround) - - [0.15.0 Pre Releases](#0150-pre-releases) + - [0.15.0 Embed Experiment](#0150-embed-experiment) - [Changelog](#changelog) ## Features @@ -190,24 +190,16 @@ Load all files from directory `scripts` as key/values into `configMap.scripts.da ## Order Workaround Until [issue 2555][issue2555] is resolved in CUE, there is a [temporary workaround](examples/workaround/). -## 0.15.0 Pre Releases - -`0.15.0-alpha.1` is the first pre-release in the 0.15.0 series. It's based on cue v0.9.0-alpha.5, -so [cue module support][modules] has landed! Cuegen "components" will be disabled when the new cuegen behaviour -is enabled by setting `apiVersion` to "v1alpha3". All options in `cuegen.cue` files, except -`cuegen.spec.export`, which is the new `objectsPath`, are gone for now. So a minimal `cuegen.cue` -file, with the default export path of `objects`, could be - - cuegen: apiVersion: "v1alpha3" - -When no cuegen specific attributes are used, executing `cuegen` in some cue directory should produce -the same output as +## 0.15.0 Embed Experiment +Cuegen `0.15.0` is based on cue v0.10.0. When `apiVersion` is set to "v1alpha4", cue attribute handling +is removed in favour for cue [native embedding][cue-embed]. Right now sops encrypted files need to be +named like `.sops.` for formats supported by sops, otherwise like `..sops`. +They will be temporarily decrypted to files named like `.`, and removed again after Yaml +output was generated. cue export -e objects --out yaml | yq '.[] | split_doc' - -All 0.15.0 pre releases, and also later releases will be backwards compatible, at least until release -1.0.0. +All releases will be backwards compatible to current `cuegen` behaviour, at least until release 1.0.0. ## Changelog @@ -252,4 +244,5 @@ All 0.15.0 pre releases, and also later releases will be backwards compatible, a [cfgschema]: internal/app/schema.cue [gh2243]: https://github.com/cue-lang/cue/issues/2243 [issue2555]: https://github.com/cue-lang/cue/issues/2555 -[modules]: https://cuelang.org/docs/reference/modules/ \ No newline at end of file +[modules]: https://cuelang.org/docs/reference/modules/ +[cue-embed]: https://cuelang.org/docs/howto/embed-files-in-cue-evaluation/ \ No newline at end of file diff --git a/examples/embed-experiment/cue.mod/module.cue b/examples/embed-experiment/cue.mod/module.cue new file mode 100644 index 0000000..ef1e850 --- /dev/null +++ b/examples/embed-experiment/cue.mod/module.cue @@ -0,0 +1,4 @@ +module: "cue.example" +language: { + version: "v0.10.0" +} diff --git a/examples/embed-experiment/cuegen.cue b/examples/embed-experiment/cuegen.cue new file mode 100644 index 0000000..320fefe --- /dev/null +++ b/examples/embed-experiment/cuegen.cue @@ -0,0 +1,3 @@ +package main + +cuegen: apiVersion: "v1alpha4" diff --git a/examples/embed-experiment/main.cue b/examples/embed-experiment/main.cue new file mode 100644 index 0000000..0abace5 --- /dev/null +++ b/examples/embed-experiment/main.cue @@ -0,0 +1,14 @@ +@extern(embed) + +package main + +objects: [ + { + Kind: "ConfigMap" + spec: {} @embed(file=values.json) + }, + { + Kind: "Secret" + spec: {} @embed(file=secrets.json) + }, +] diff --git a/examples/embed-experiment/readme.md b/examples/embed-experiment/readme.md new file mode 100644 index 0000000..f4cc79a --- /dev/null +++ b/examples/embed-experiment/readme.md @@ -0,0 +1,17 @@ +## Embed Experiment + +By setting `apiVersion` to `v1alpha4` in `cuegen.cue` the experiment is enabled. +`Cuegen` will decrypt all sops files, so values from `secrets.sops.yaml` will be +used. + +Running `CUEGEN_SKIP_DECRYPT=true cuegen` will use values from `secrets.yaml`. +You could get the same result with + + cue export -e objects --out yaml | yq '.[] | split_doc' + +which might be useful for (cue) debugging purposes. + + +To run this example you need to set + + SOPS_AGE_KEY=AGE-SECRET-KEY-14QUHLE5A6UNSKNYXLF5ZA26P3NCFX8P68JQ066T7VJ6JW5G8FHWQN4HAUQ \ No newline at end of file diff --git a/examples/embed-experiment/secrets.json b/examples/embed-experiment/secrets.json new file mode 100644 index 0000000..01d965a --- /dev/null +++ b/examples/embed-experiment/secrets.json @@ -0,0 +1,4 @@ +{ + "USERNAME": "example-user", + "PASSWORD": "example-pass-123" +} diff --git a/examples/embed-experiment/secrets.sops.json b/examples/embed-experiment/secrets.sops.json new file mode 100644 index 0000000..28ec35e --- /dev/null +++ b/examples/embed-experiment/secrets.sops.json @@ -0,0 +1,21 @@ +{ + "USERNAME": "ENC[AES256_GCM,data:50bGUSewU6hm,iv:GLJosnkWg17+rfs+pRs/61UpKkkCUBdcdjJvaNBKYPw=,tag:Ru9+KvJ040B13pq5ccoyfg==,type:str]", + "PASSWORD": "ENC[AES256_GCM,data:LOUgGddQg5axEQ8=,iv:nHdyZXtlU+Nn5XpVtr/N6/m2BFMYmLbl2qeGt+kJE4I=,tag:WZwyYN92q0vtDON3geNHhA==,type:str]", + "sops": { + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": [ + { + "recipient": "age13643rcqprsmy33ff4rgj2strpyhxgzu3x6lvyrzvhsqqjvmk9d3qe59qn8", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVYUtXc1E0ZTloeG9scnBK\nTThZdnZYcENJelN5TjJYWTYxOWlsREEyU0Q4Ck5ZM3FnN08ycDcxdmhJQkp3TTV4\neGhOeFR1SzFMbWc4OFlHOGtnT25hbWsKLS0tIEIzS1NibGQzVDNvMXA4MlZ0TGdC\nenFGbzdXeC9tV2VIdGdIaWlMMnRjNUEKv+ZnieZSNuwfAaZratHR0mRx30HA/TLZ\nCGYDZLO7EXcV+XDVUtG0KoZB/28Olnxr0tz7cL8RonHeQadUy8zjtA==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2024-09-02T09:08:54Z", + "mac": "ENC[AES256_GCM,data:njrsy9sYsYTGq34Qk7lcRoE+SawGFGyy9OzQHDURSZkUVmYYIwAZPfR0SerXnLaolsVoePVQqtFWcHiV/UYBeFB21I5qM3fyCjv6lD4fow2cHieOx6b8LvL+Z/gUcBAmMN1WBxZK01oYuH8n2tz2VaMWiR0qsN0QIT7mWGvapkQ=,iv:2z+5d/Ga/9vwGLmBw0DXnA3+mWEnyPfjRFdwX5UYK3Q=,tag:Vi/bEgRg2xpIGafWBrqFXw==,type:str]", + "pgp": null, + "unencrypted_suffix": "_unencrypted", + "version": "3.7.3" + } +} \ No newline at end of file diff --git a/examples/embed-experiment/values.json b/examples/embed-experiment/values.json new file mode 100644 index 0000000..e72d4f2 --- /dev/null +++ b/examples/embed-experiment/values.json @@ -0,0 +1,4 @@ +{ + "DB_HOST": "mydbhost", + "DB_PORT": "5432" +} diff --git a/internal/cuegen/v1alpha4/wrapper.go b/internal/cuegen/v1alpha4/wrapper.go index c62b680..0dddc8e 100644 --- a/internal/cuegen/v1alpha4/wrapper.go +++ b/internal/cuegen/v1alpha4/wrapper.go @@ -110,12 +110,20 @@ func decryptFile(path string) error { wlog.Warn("found unhandled extension", "ext", ext) return nil } + nonSopsPath := toNonSopsPath(path) if nonSopsPath == "" { wlog.Warn("skip", "file", path) return nil } - _, err := os.Stat(nonSopsPath) + + wlog.Debug("decrypt", "source", path, "target", nonSopsPath) + cleartext, err := decrypt.File(path, ext) + if err != nil { + return fmt.Errorf("%v: can not open decrypt file: %v", path, err) + } + + _, err = os.Stat(nonSopsPath) if err == nil { err := backupFile(nonSopsPath) if err != nil { @@ -125,11 +133,6 @@ func decryptFile(path string) error { restoreAfterRun[nonSopsPath] = "" } - wlog.Debug("decrypt", "source", path, "target", nonSopsPath) - cleartext, err := decrypt.File(path, ext) - if err != nil { - return fmt.Errorf("%v: can not open decrypt file: %v", path, err) - } f, err := os.Create(nonSopsPath) if err != nil { return fmt.Errorf("%v: %v", path, err) diff --git a/scripts/test-all-examples.sh b/scripts/test-all-examples.sh index ffab284..693a3a7 100755 --- a/scripts/test-all-examples.sh +++ b/scripts/test-all-examples.sh @@ -40,6 +40,14 @@ cuegen https://github.com/nxcc/cuegen-remote-test.git | grep -q 'field1: test te cuegen "https://github.com/nxcc/cuegen-remote-test.git?ref=subpath#apps/app_b" | grep -q 'field1: test yaml 5678' echo " OK" +( + echo embed-experiment + cd embed-experiment + export CUE_EXPERIMENT=embed + cuegen | grep -q t0p53cr3t + CUEGEN_SKIP_DECRYPT=true cuegen | grep example-pass-123 +) + # done if [[ $cleanup_demo_cue == 1 ]]; then