From 85accf733042c190825e9de55b6e656bf747906e Mon Sep 17 00:00:00 2001 From: Philipp Hossner Date: Tue, 6 Apr 2021 07:20:42 +0200 Subject: [PATCH] Add helm-secrets-encrypted values template file (#1701) Secret files ending with .gotmpl are now also rendered as a gotemplate. ``` releases: - name: myapp secrets: - secrets.yaml.gotmpl ``` Note that currently, .gotmpl files must be valid YAML files as well. The expected use-case of this feature is to compose a YAML array from values and encrypted secrets. Without this feature, you would have tried to do something like the below, which didn't work. **Example (doesn't work!)** `values.yaml.gotmpl`: ``` environment: - name: MY_EXTERNAL_IP value: | {{ exec "./get-external-ip.sh" (list "") }} ``` `secrets.yaml`: ``` _sops: #... environment: - name: MY_SECRET_VALUE value: (encrypted by sops) ``` `helmfile.yaml`: ``` releases: - name: foo values: - values.yaml secrets: - secrets.yaml ``` This doesn't work because `values.yaml` and the decrypted `secrets.yaml` are passed to `helm` to be merged, and helm overrides the array instead of merging or concatenating the arrays. **Example (works!)** Instead of `values.yaml` and `secrets.yaml`, you provide a single `secrets.yaml.gotmpl` that is a valid YAML and encrypted by sops: ``` _sops: #... environment: - name: MY_EXTERNAL_IP value: | {{ exec "./get-external-ip.sh" (list "") }} - name: MY_SECRET_VALUE value: (encrypted by sops) ``` `helmfile.yaml`: ``` releases: - name: foo secrets: - secrets.yaml.gotmpl ``` Helmfile decrypts the gotmpl by handing it over to helm-secrets and then renders the result as a gotmpl file. The end result is that you have a two-element array `environments` that can be just passed to helm. Resolves #1700 Co-authored-by: Yusuke Kuoka --- .circleci/config.yml | 61 ++++++++---------- pkg/helmexec/exec.go | 13 +++- pkg/helmexec/exec_test.go | 23 +++++++ pkg/state/state.go | 12 +++- ...D6D7BBEC03B2E66571C8C00AD18E16CFDEF700.rev | 15 +++++ ...9C8F04FB6EC2F484FA571BFC14B1BBE7F6B6A9.key | Bin 0 -> 1425 bytes ...D2A3FEE7BE52FE4BEE9A5F51E8554B3F78E49F.key | Bin 0 -> 1424 bytes test/integration/.gnupg/pubring.kbx | Bin 0 -> 1962 bytes test/integration/.gnupg/trustdb.gpg | Bin 0 -> 1280 bytes .../charts/httpbin/templates/deployment.yaml | 5 +- test/integration/run.sh | 25 +++++-- test/integration/scripts/echo.sh | 2 + .../secrets-golden/direct.build.yaml | 2 + .../secrets-golden/reverse.build.yaml | 2 + test/integration/secrets.yaml | 29 +++++++++ .../integration/secrets_templated.yaml.gotmpl | 29 +++++++++ test/integration/secretssops.yaml | 5 ++ .../v2/httpbin/deployment.yaml | 5 +- .../v3/httpbin/deployment.yaml | 5 +- 19 files changed, 186 insertions(+), 47 deletions(-) create mode 100644 test/integration/.gnupg/openpgp-revocs.d/B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700.rev create mode 100644 test/integration/.gnupg/private-keys-v1.d/199C8F04FB6EC2F484FA571BFC14B1BBE7F6B6A9.key create mode 100644 test/integration/.gnupg/private-keys-v1.d/67D2A3FEE7BE52FE4BEE9A5F51E8554B3F78E49F.key create mode 100644 test/integration/.gnupg/pubring.kbx create mode 100644 test/integration/.gnupg/trustdb.gpg create mode 100755 test/integration/scripts/echo.sh create mode 100644 test/integration/secrets.yaml create mode 100644 test/integration/secrets_templated.yaml.gotmpl diff --git a/.circleci/config.yml b/.circleci/config.yml index 9db308d3..7cd235b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ -version: 2 +version: 2.1 jobs: @@ -78,52 +78,43 @@ jobs: # thanks to https://raw.githubusercontent.com/weaveworks/launcher/master/.circleci/config.yml integration_tests: machine: - image: circleci/classic:201808-01 + image: ubuntu-2004:202010-01 + parameters: + helm-version: + type: string steps: - checkout - run: mkdir ~/build - attach_workspace: at: ~/build - run: + name: Install test dependencies command: | cp ~/build/helmfile ~/project/helmfile cp ~/build/diff-yamls ~/project/diff-yamls cp ~/build/yamldiff ~/project/yamldiff - - run: make -C .circleci helm2 - - run: make -C .circleci kustomize - - run: make -C .circleci minikube + if [[ "<< parameters.helm-version >>" == v3* ]] + then + make -C .circleci helm + else + make -C .circleci helm2 + fi + make -C .circleci vault + make -C .circleci sops + make -C .circleci kustomize + make -C .circleci minikube - run: name: Execute integration tests environment: TERM: "xterm" command: | - make integration - - integration_tests_helm3: - machine: - image: circleci/classic:201808-01 - steps: - - checkout - - run: mkdir ~/build - - attach_workspace: - at: ~/build - - run: - command: | - cp ~/build/helmfile ~/project/helmfile - cp ~/build/diff-yamls ~/project/diff-yamls - cp ~/build/yamldiff ~/project/yamldiff - - run: make -C .circleci helm - - run: make -C .circleci vault - - run: make -C .circleci sops - - run: make -C .circleci kustomize - - run: make -C .circleci minikube - - run: - name: Execute integration tests - environment: - HELMFILE_HELM3: "1" - TERM: "xterm" - command: | - make integration + export TERM=xterm + if [[ "<< parameters.helm-version >>" == v3* ]] + then + HELMFILE_HELM3=1 make integration + else + make integration + fi # GITHUB_TOKEN env var must be setup in circleci console @@ -156,9 +147,9 @@ workflows: - integration_tests: requires: - build - - integration_tests_helm3: - requires: - - build + matrix: + parameters: + helm-version: ["v2.17.0", "v3.4.2"] - release: filters: branches: diff --git a/pkg/helmexec/exec.go b/pkg/helmexec/exec.go index 88845d19..56c88cd8 100644 --- a/pkg/helmexec/exec.go +++ b/pkg/helmexec/exec.go @@ -278,7 +278,14 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str if len(decSuffix) == 0 { decSuffix = ".yaml.dec" } - decFilename := strings.Replace(absPath, ".yaml", decSuffix, 1) + + // helm secrets replaces the extension with its suffix ONLY when the extension is ".yaml" + var decFilename string + if strings.HasSuffix(absPath, ".yaml") { + decFilename = strings.Replace(absPath, ".yaml", decSuffix, 1) + } else { + decFilename = absPath + decSuffix + } secretBytes, err := ioutil.ReadFile(decFilename) if err != nil { @@ -308,7 +315,9 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str if tempFile == nil { tempFile = func(content []byte) (string, error) { - tmpFile, err := ioutil.TempFile("", "secret") + dir := filepath.Dir(name) + extension := filepath.Ext(name) + tmpFile, err := ioutil.TempFile(dir, "secret*"+extension) if err != nil { return "", err } diff --git a/pkg/helmexec/exec_test.go b/pkg/helmexec/exec_test.go index 86af61ad..82af63ba 100644 --- a/pkg/helmexec/exec_test.go +++ b/pkg/helmexec/exec_test.go @@ -289,6 +289,29 @@ Found secret in cache %s/secretName } } +func Test_DecryptSecretWithGotmpl(t *testing.T) { + var buffer bytes.Buffer + logger := NewLogger(&buffer, "debug") + helm := MockExecer(logger, "dev") + + tmpFilePath := "path/to/temp/file" + helm.writeTempFile = func(content []byte) (string, error) { + return tmpFilePath, nil + } + + secretName := "secretName.yaml.gotmpl" + _, decryptErr := helm.DecryptSecret(HelmContext{}, secretName) + cwd, err := filepath.Abs(".") + if err != nil { + t.Errorf("Error: %v", err) + } + + expected := fmt.Sprintf(`%s/%s.yaml.dec`, cwd, secretName) + if d := cmp.Diff(expected, decryptErr.(*os.PathError).Path); d != "" { + t.Errorf("helmexec.DecryptSecret(): want (-), got (+):\n%s", d) + } +} + func Test_DiffRelease(t *testing.T) { var buffer bytes.Buffer logger := NewLogger(&buffer, "debug") diff --git a/pkg/state/state.go b/pkg/state/state.go index ba0e5656..60915670 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2601,7 +2601,7 @@ func (st *HelmState) generateVanillaValuesFiles(release *ReleaseSpec) ([]string, } func (st *HelmState) generateSecretValuesFiles(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) { - var generatedFiles []string + var generatedDecryptedFiles []interface{} for _, v := range release.Secrets { var ( @@ -2652,8 +2652,16 @@ func (st *HelmState) generateSecretValuesFiles(helm helmexec.Interface, release if err != nil { return nil, err } + defer func() { + _ = os.Remove(valfile) + }() - generatedFiles = append(generatedFiles, valfile) + generatedDecryptedFiles = append(generatedDecryptedFiles, valfile) + } + + generatedFiles, err := st.generateTemporaryReleaseValuesFiles(release, generatedDecryptedFiles, release.MissingFileHandler) + if err != nil { + return nil, err } return generatedFiles, nil diff --git a/test/integration/.gnupg/openpgp-revocs.d/B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700.rev b/test/integration/.gnupg/openpgp-revocs.d/B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700.rev new file mode 100644 index 00000000..ac7c30f8 --- /dev/null +++ b/test/integration/.gnupg/openpgp-revocs.d/B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700.rev @@ -0,0 +1,15 @@ +:-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iQG2BCABCgAgFiEEstbXu+wDsuZlccjACtGOFs/e9wAFAmA4+f8CHQAACgkQCtGO +Fs/e9wBN4wv/S0D4RCu5+BLt8y0vpAI9o1iRXj+yzOvPJUCm/QH1kN39saeI3rbr +8pyytpmzO5wIr+G+6BHh56p3NzjxWxfIt/RQ1vPMYf/dxzvtRuvYY00Fu683A65i +UqU9hiA6q1310OrMyEds4GmIteM++5xtKhV2s3A4bXJp6QD83MKV3m1IFYJ5cWfM +GmUSVlXBMiZ5Vfe8a04KaPKU3EkVSSIxLsvOW5+tPDZzkdUAHMCoHRAIBeOd7Aqo +uNytWylZtk1SeSeglbpm22NrXdvQbxV2oZplEazegqkydyUy8XmCh/57t1lHekAZ +Dcw0XgXu1s5TWj0vXa2g9sW+CKLGsDNg5XYp2cR4UGkGXCctp7aZb6k1+wv33zjB +hEL03GRq4AQ7yRzMsP0ue1YveolUfHRy+9OlFVdN25rL2VOvIkAxknnpe1c0gPLk +NOer0NAVPzE8QzHFQIDICriJ2urfzMm/nfa2UHW8O81opib5LNRbcPz+GOmKEgLf +aKRmcXNIZkPx +=ohmg +-----END PGP PUBLIC KEY BLOCK----- diff --git a/test/integration/.gnupg/private-keys-v1.d/199C8F04FB6EC2F484FA571BFC14B1BBE7F6B6A9.key b/test/integration/.gnupg/private-keys-v1.d/199C8F04FB6EC2F484FA571BFC14B1BBE7F6B6A9.key new file mode 100644 index 0000000000000000000000000000000000000000..aabddb9a32fe6d39176932120194cc9723ad6c05 GIT binary patch literal 1425 zcmV;C1#bE%F)=!Da%py9bY(4TWqBwwI&yPiC^0&2GdMLm0NAva-Pyi{{r>=l^-RA< z2E`>*^B%dB53FYx)B^l2I2l^B0+{(MjPAj7wPVy1DPwOb;Y-MZjR`Gx^_`J{E>wZ< zTTj7(+oA}!78bqti%$iSrRF#+)*dJ*e3#45pXTn_uMs~sWL1&W+uQvnnJ_JOmQm(be0JFs@h#>f!`jomyc|*`RWW6rS>M}DzxLv1d zp80AMG}IM#geT>;11TFEoEm)vQV}U97d8py!P!7(se%1_(zr_iOmas3zeE*d_>c;% z^E8M%znvA&4z1SIikqg90yqg(UotY-*wqBL1~NdvRzG9fE0Y`;8*4jqHaYM^u^0?; zAu-_(_beAr)Hv^iFHe50fwIRoA-I`0Xx&p?Xvw$>0#V?-&3x}0&g4c1k#3@8! z@_eRWckA-7qsxt;0X4Q#D*Tu0EVM9y=2ztsAqJ*CTKGiD9{LdzlGLfG4Y2<>Iz=)e zuA3~p(J3e~I%P9D0RRChC^0%@GdMIl3>`a8Q(E!cUpE-EONuF0tn6=fXjd#cT$4sw zYQfEQBp|entsckGXp-)_>80E}-15ZA^bIvs97?G=c-+0=6>tk)#*c1Fcj8+NE&jTHA)! zKzwp47~re+}gxf0)pGYoAC&3 zBF`~p#Zknrnvm_2*PG}zeRpS)Sr%1hcEOj2#~cgi8WJ=%Bnz6HPy@nWl-ERgyLyuq zap&7i7Xmc;uGS@6Ob0Ooc%CI);c#&3+jX)usR?4lq~NVL06E~ACg#aX)JwBAi{p<= zVI{lJ5$Oc9A1y%va0PbfUbV*(2;$QgF~M|~JyXN=Q%p2cifZz$PZ~Ych9Y|FaPeKZz%RC)s&pUQ0&A<2O zSb)E@#8>^m!lm?_w${7`QnmK)aL)m?=kN>1L8x`<^{ncN!Fgm44DE_%QmJ!(Tg61W z16aUsn30KB&!#-6o51*D=2Irktj$G_>-#uEg)Z)_9iplUm$?bhkjbuk$X=5=j<9hA z{a0k@Fs=nA5-KT`_+7N$muvg``ch@K(+l1{DSgQsv9MHjvbiZJF*YQ+FHC z3X8oHe%bG4Fns_Yo0t=*$5*$`IObKzOI^yB9^&tcaIjo?%<5SC?6R`!hyS26h~C|v zzQa!}tjie498DiFk*kV+!i&As4`4Eku&vhguf1d7HAZgcPW~YB$0-;Zi^l_n9wHw- ztn^Kpd&^x}i{{bz$eCvXoo}yjXv&PcJ|&DU5dtpRDJU^Ibul?II#%d$=1m=Z3P(5C zOsO2A za$94y8NRJpsZa!#QchFGYzCR?B8wWVDN>n6hONS*MXXhuH%Y@Raz?<^dCApKZf7_h znAd>z#R#tg<#_}2Y<9%YPHqljjf5vF6o`(_gWTZgUYjhIhJfm!;aUZEB1tT2vSC7* fA^@V8Uvh2_U>~;`?_rK#L+_@Mq?GSpDk&)`Bjc zu?`^s{SM*6nneigy0U>#qJV99pFZIh{6UwP zz{oCEI$3XAR}g;`Q~*(X#@Fj>Z#N_By4C^h&oqrO)>?1=Xd;1u`|AT6;Ytd_Aj$YA z2e#LP3hgkE-*<7;7J^S2xh~^0EZ|zHI_&ghnvR#8Hfe8gm{(D5>Pl$o=g=P*R@a0| zn8}?Xj(`{p?^&h?d3S!LPz-<6#qy+<#!CrTsQ7;v_}&y$p7b9%C$o!N5?vV3Y+U%M zFO2W5%PA-^I%P9D0RRChC^0%@GdMFkMj)=)cuY>NU^XVPZo>x)4RI!94Sej{m|c zm>a{$cwv_#N@m--6CDfu>ji^g>Vl;86vuptgPPOv2|z8Lx?RaQra^guavZxnq>o;S zphf%6v{#m@=_gs_xKA>36)*b%L3Re3IgB|zxdzS$T;;d;=)Bi3@VNCUC^0&4F*!3j z0K;*tJ6=s2liIe|E^g}fuDcGbEgz8=j5V@I6js8-K7h*~o@@XK2(#Tms_De;85w_x zFhNFoV`cCEyzQv==lk<<#iNXR&{&h|3;FP;vp-fSXD<5Q4$#a?Uyk7p_e>uK*M<2X z;U2T8rSkZP;H7n25}Ty4)k>^u`nZQ!`HS3&p2&$l5$L@6!Fq^}Zoc@Htr!6V%GO}& z%305?pYyzx2bKa5U_)(MxJgTx2*r25b00E1yk5Uda<%V&PbnxdI&m>MGdcju&fa%` zKA>Ejo-`L=9^O}Am=pJ#qT66!Wsae5v9SruW9R}c7tW2$H{;AgJJI>Ln^C9uxzQ{r ztJY1L8oa6zYBw>9lvAryH;uxQr<)L1#f`{CS)xxFRGl`7GX9&w#By>vKtNlFRHUP` z1j5gBJ^Jl@_y~+}e9L$Gx?VW}yCY-Qc}fMXAI)+L0&|>$rH$KU5b0|guJm-Yeq<_N z1*>3;oT%=U2kG_b(`aDS`TU1%D+)ZLyZAAuj2Xo#C^0&9F*!0iVgO@;Rk~P6NMS6X zb;`tggtw~>Ib-%R$C3R#RvSkV$5K8k(dWe$wPG|@+|P5p%|>5w@Hi#LE{yzV*aM#l zuMFV(6l@*%pfm3!vu}dL#JT_?ul8)(&nnJ8q`_Rz=eIF2TQq+6N5jw7wRMcf28Wv# zgi3<8AMJ?clF%XS@qtm5s-#kv1A!O@2|*IOb|hrmaU-13RncN}!2dl^$0tt54dlvx eUsF$4aopTT22M=PVnvZRI7L;`$3GTkDJdz5?6#x; literal 0 HcmV?d00001 diff --git a/test/integration/.gnupg/pubring.kbx b/test/integration/.gnupg/pubring.kbx new file mode 100644 index 0000000000000000000000000000000000000000..cbab1b75c902c42db86c460c15a8b8841be00c90 GIT binary patch literal 1962 zcmah|2Q=K-9{&FagCR;VX0c;NqW2P==n^$L6P^||VWKQi));Jb(ViAPA#0<=5M>Z$ zmuOKEtE?9c!G`E<)OjO$d)_bF;&Z^*X>ii38TmABmS|Gp-01zaVp)QZq*J!`){{_?^P%c~fU@9$@Z-UIgbYsrP znKwV3Q-H?@CY^@RUP0?UWNS8SwHIOnawetx9i|bIcPx>z*&Y1aeS$;O9V<#Q?vF`j zlngy6%D_umk~1*=n{+0mrctFo+p-3K)EiYB1Qg(ulW!!X@3<$E1c zLu+#KIxS8we2R~KITR+iLgIv%n`lIN`3iY{q_bof73NlCT<)IH@~Xn0N4#$_2227C z&O7zE+{x*%nmvUCway~0QI?v?iKM5M84zVg8)rGW>FM8To1t=AUA8yf{}9jOL-5{L z3sh9u)~!b{2cl(3tVa^u<`c?Wanj~dHF&~XMRZHPlJ`d|C+~q4CWysC$GgZa-jPoR z^cnu;m6#dLkln~i=g{@tSI>r0OTimWmSShQ>k^GJ(JOY#SJBW)O$=FY5P8DRkvUOS zb>$UBSyf*SUHep`eH>s10q_-7J+Fse-~0eHqO7of9w;+cDyRohsXvuzc|3CUd-%XZ z${p*c`LB7%H+d7m5n2uq1}MYPwExRPbdXD}A-ptnOpFZl5GWUnk%0+93y08v5F`lU zjs{?iY=0R}gp(O4uUx+w2;C?3Kp|b3b38$7!m})n*ao7Ux7ORhUrHZ~+R$@psy1#_ zKK)}z@D)ae5=(k=@iJ(Adi`rpX)PY}8;y?JS#S!hh zI{4Wu24foG&hgp~dOI0MRPj>z!Dh$K)R$A12g}nItBQy5Z-hYo!6I_hZ5OwioDBB? zH09|K>r(61b=$j>{V^AR*RI(Y`(Yt=$tvGhrE^%l*r0$kN02b#j;gXxXNX>7lV6Z8 zU(|Q2pwJ`e!VQ9#%Jg;{OMTWhqu5skp$Wg*_&>42*^mQ8a5-Pz2V|{wJ9r3~iY3Ux zZ1|^U+tp3bz*Xkl^ zkcOFUi;l$vfmC;eJsHBJx~BxiSuH6Wiw!CliFsC?N=eVVkQMV~IL&ORqFm@z{IE(| zGzegpSB>0(j zZeCZvl&z`**3pg)$7u~%MD$Iq-^VIlTPIF}8>0%TvXdC>g|`46f4WY?OEQA}iW(pb z(>G1U!Zu{m=R*S~;4$Vrtx`)05(}6r)i3+^3es{56@9P|^Xx4A*NnVBua5B}Y^UOk z@&<~~Y0(JgEr&|_u+XTAJIuI=-reUpea4J-Ka+6?@*Jmi@jkzba6|Ilt4@fq2ae<_ z>6ES7p|3Gb1e<6P)S#jMPtchEGf;2{6U9A$`A?#rS#b}Yr`6PON1G~}#%L>;KN2+W zn|0JRH}qE;5-;c;sW{1&0|*@{txo&UTEaye%iAOMP?$d}r9RIt`8$ z1?zATmwt{U65P4W+Emvuv$Ref)Cle%<~~lG3){{)!a~^GlONm>T-%J!BYZ+<_}$Ze zogLr%<)vEYFru}CDcf#~BF}kh{_p@ka7P%#*7w!`myQT<_c(_SD-G2qj+A=I9 U`FjlVH3vpC$c6Bh0dMu-pAfNOV*mgE literal 0 HcmV?d00001 diff --git a/test/integration/.gnupg/trustdb.gpg b/test/integration/.gnupg/trustdb.gpg new file mode 100644 index 0000000000000000000000000000000000000000..d4517bb4d5c7c5295a8a3bfd156ab6cb9d72480f GIT binary patch literal 1280 zcmZQfFGy!*W@Ke#Vqi$H_{GV99WZiX7sn7CRfiEIV1dza8K&VP2l3Zv{L&|Wc^Ecb zyT1Dk^QLF1g(nVhUF;J(fA2d38^m&Xgd2DnCcc%65BzuhPwCbd#V3zz&W?Imy&I|y Hp^O0lY9k!z literal 0 HcmV?d00001 diff --git a/test/integration/charts/httpbin/templates/deployment.yaml b/test/integration/charts/httpbin/templates/deployment.yaml index d24b7ed9..f149c099 100644 --- a/test/integration/charts/httpbin/templates/deployment.yaml +++ b/test/integration/charts/httpbin/templates/deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: metadata: @@ -10,6 +10,9 @@ metadata: heritage: {{ .Release.Service }} spec: replicas: 1 + selector: + matchLabels: + app: {{ template "httpbin.name" . }} strategy: {} template: metadata: diff --git a/test/integration/run.sh b/test/integration/run.sh index a32fb3ef..8d246bb1 100755 --- a/test/integration/run.sh +++ b/test/integration/run.sh @@ -20,6 +20,15 @@ test_ns="helmfile-tests-$(date +"%Y%m%d-%H%M%S")" helmfile="./helmfile --namespace=${test_ns}" helm="helm --kube-context=minikube" kubectl="kubectl --context=minikube --namespace=${test_ns}" +helm_dir="${PWD}/${dir}/.helm" +export HELM_DATA_HOME="${helm_dir}/data" +export HELM_HOME="${HELM_DATA_HOME}" +export HELM_PLUGINS="${HELM_DATA_HOME}/plugins" +export HELM_CONFIG_HOME="${helm_dir}/config" +HELM_SECRETS_VERSION=3.5.0 +HELM_DIFF_VERSION=3.0.0-rc.7 +export GNUPGHOME="${PWD}/${dir}/.gnupg" +export SOPS_PGP_FP="B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700" # FUNCTIONS ---------------------------------------------------------------------------------------------------------- @@ -45,26 +54,32 @@ function retry() { done } +function cleanup() { + set +e + info "Deleting ${helm_dir}" + rm -rf ${helm_dir} # remove helm data so reinstalling plugins does not fail + info "Deleting minikube namespace ${test_ns}" + $kubectl delete namespace ${test_ns} # remove namespace whenever we exit this script +} + # SETUP -------------------------------------------------------------------------------------------------------------- set -e +trap cleanup EXIT info "Using namespace: ${test_ns}" # helm v2 if helm version --client 2>/dev/null | grep '"v2\.'; then helm_major_version=2 info "Using Helm version: $(helm version --short --client | grep -o v.*$)" ${helm} init --stable-repo-url https://charts.helm.sh/stable --wait --override spec.template.spec.automountServiceAccountToken=true - ${helm} plugin ls | grep diff || ${helm} plugin install https://github.com/databus23/helm-diff --version v2.11.0+5 else # helm v3 helm_major_version=3 info "Using Helm version: $(helm version --short | grep -o v.*$)" - ${helm} plugin ls | grep diff || ${helm} plugin install https://github.com/databus23/helm-diff --version v3.1.3 - # ${helm} plugin ls | grep secrets || ${helm} plugin install https://github.com/jkroepke/helm-secrets --version v3.5.0 fi -info "Using Kustomize version: $(kustomize version --short | grep -o 'v[^ ]+')" +${helm} plugin ls | grep diff || ${helm} plugin install https://github.com/databus23/helm-diff --version v${HELM_DIFF_VERSION} +info "Using Kustomize version: $(kustomize version --short | grep -o 'v[0-9.]\+')" ${kubectl} get namespace ${test_ns} &> /dev/null && warn "Namespace ${test_ns} exists, from a previous test run?" $kubectl create namespace ${test_ns} || fail "Could not create namespace ${test_ns}" -trap "{ $kubectl delete namespace ${test_ns}; }" EXIT # remove namespace whenever we exit this script # TEST CASES---------------------------------------------------------------------------------------------------------- diff --git a/test/integration/scripts/echo.sh b/test/integration/scripts/echo.sh new file mode 100755 index 00000000..5fdd6033 --- /dev/null +++ b/test/integration/scripts/echo.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +echo $1 \ No newline at end of file diff --git a/test/integration/secrets-golden/direct.build.yaml b/test/integration/secrets-golden/direct.build.yaml index aaa7b722..a7424cd7 100644 --- a/test/integration/secrets-golden/direct.build.yaml +++ b/test/integration/secrets-golden/direct.build.yaml @@ -13,3 +13,5 @@ stringData: key_1: value_1 key_2: value_2 key_shared: value_2 + my_other_key: MY_OTHER_SECRET + my_templated_key: MY_TEMPLATED_SECRET diff --git a/test/integration/secrets-golden/reverse.build.yaml b/test/integration/secrets-golden/reverse.build.yaml index ef7ada09..b2152fe9 100644 --- a/test/integration/secrets-golden/reverse.build.yaml +++ b/test/integration/secrets-golden/reverse.build.yaml @@ -13,3 +13,5 @@ stringData: key_1: value_1 key_2: value_2 key_shared: value_1 + my_other_key: MY_OTHER_SECRET + my_templated_key: MY_TEMPLATED_SECRET diff --git a/test/integration/secrets.yaml b/test/integration/secrets.yaml new file mode 100644 index 00000000..8266a3cf --- /dev/null +++ b/test/integration/secrets.yaml @@ -0,0 +1,29 @@ +my_other_secret: ENC[AES256_GCM,data:1a4CrBDijRelwRkFea5M,iv:NOLrOJwXq5ldgh7dfd80G2XKC/JaHw8ozT4DX1O6x1U=,tag:jJZJSSicLNFU8/m5uGeznw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + lastmodified: '2021-02-26T15:11:53Z' + mac: ENC[AES256_GCM,data:Dl5X27oM8Ze4L6LX8zdJdMFiLvPDKl3ZrWSnR8Yn6zFRyUvd6Hy5uCW1JCZHpTtxPvvFCzmsJ4J9NTc2esbWg1YzPT2o3npbq8JXUajy2Dy624KqX+sq4dRgdKXyCnLEy4SL6VcuyjmbBP9qjZpRx2sbuFWdnQjt1qLJ7z/I+BE=,iv:tFhPgOjS/pP6pQatWiUlsS0+X77J6E0DOY48F0xdorM=,tag:wP1PjMeavF0U7GF/Mvgt5Q==,type:str] + pgp: + - created_at: '2021-02-26T15:11:52Z' + enc: | + -----BEGIN PGP MESSAGE----- + + hQGMA7Px5yX5jd+nAQv+KHcMR2P/4ywivwYMEIchWTxeSnA7foBVwxqpO3bcqOU8 + 2e4O2N6vI74u3rff2UzDaBENXOzdlcl8aBAkNaKsjv1vTLFiGkt28ZSYA4mMbLQi + JRbr1Ld376L8TXfP/roGJL3RsXVVXZQQHTw4DV+Wbb2P8bgROqN9edcuDB9JMyLK + GQPHC0QUCGVY+EtU6cTJ2ghZ3BxpBdwgm0uxxMT0W899ivP/2qmdMF+wGOVCO4dk + t0IiqZdck+AybdXMT+h2B949VvNQtotpSQEARuv89BPH71ynjayFnp28KQU3PhGN + KdJSiBZMmb9RlkSU56wGmglKGFqpSKDr8+jcUExN3QZhjZuC/k6qneg9xaKRmlno + B0a0TSDVEwd1qKVIsN29ALSAxWomAcs0H3gtZUd+8TEEYYm8F9dVCIf4npot9S1I + yASFvySKgWDgRttxbkwfAq0uxDGqOBRL67BVqqMk06jaEVX5x+TAwME1t7FYnOfk + +Z9wmAYcihL7iZg3HclU0l4BZSsDugB+YGubBfN/hkORQkMa2anyfzkshC181eJ1 + mjXFgaPMj03vlBegGUUW+V5KUzmKT9czbWxLWq9KZtAOQTkI0kEz0jsJ8W/up3bU + eXR6z6sM5pHR7rn9liOj + =Ko7j + -----END PGP MESSAGE----- + fp: B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700 + unencrypted_suffix: _unencrypted + version: 3.6.1 diff --git a/test/integration/secrets_templated.yaml.gotmpl b/test/integration/secrets_templated.yaml.gotmpl new file mode 100644 index 00000000..e06b7413 --- /dev/null +++ b/test/integration/secrets_templated.yaml.gotmpl @@ -0,0 +1,29 @@ +my_templated_secret: ENC[AES256_GCM,data:tQeqvLecCi2sJkoZbbA5Vj0pyBqMqz7YIpmOWUTViEQi/UARNYHk4zZMW+IegElwW83yC9NsCHAuYg==,iv:RR75PQ4f6nteg+6ciizQxcTdiEAzfW0CpTg+3VtExBw=,tag:iO5SflR/Ny4oUs9LhxkN8w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + lastmodified: '2021-02-26T15:44:26Z' + mac: ENC[AES256_GCM,data:9rpFipXjZdMxEnxDTKwmQ9NwLsoZ3PLtIeWIrOEMLkVCBiOIoYHdEcKt362o59+pyPLGu2Cg5XWcuIcy7HK5vYj7r97U7aI5OJ1yEzdNjl/D+lG9mCIMQ8CoHM4HlwIncBiDu6JTk4ufAGwAbzBagOWF6lFfgMC48s0f6E8AgDk=,iv:O49gGSGNsjtEBvOxoQGqh4g4WkrN+uDaWVrvXCmIRS8=,tag:Wnbojg645yuakxOHuE2v6w==,type:str] + pgp: + - created_at: '2021-02-26T15:44:26Z' + enc: | + -----BEGIN PGP MESSAGE----- + + hQGMA7Px5yX5jd+nAQv/desIyeJfXKCYB4LGBNp0N5InJnWUM5MBiGd97s1dDIP+ + Iq7aFZL7K9YjVL9+dJuKZcInRxaLk6EwhHBlxohjoL3jAbNOM/5BcROdGbAeU+el + O9k/RfoQBwmuZj9VezGNEggS4dRn2n5/hvnj6n1dusvpkTAt/DaIbcI6KkrQ1PJt + 0Tb5kSqkpobge9Hefm7v1RPz+ywDlfBfpRrhikQobIgvNaBoDSwb2JPkdui4gC5r + jj8QZn8V3wB6ulgGJCBstG4iI2xKeuMH9ejk6mfQDHPCEAgKgN+DatqQNPKiFezC + pUe7vg1LnyyZD6vE88wT15p2sB69MeBE2SNaYdNrhLNq4hOQxRmNCV5Ra1MuxA2d + 3ZdTwCvEe9n7YAYU3+Cht42urPqJyRlO/8acEhQ4STS3uelM/GWqbcjV5JNN70Jv + 44E7V+1Xx4MWhpFUA1VJKwYFkl+n/aXla6vr2WxG4AHk0dMe8658fLIwJn4AONW8 + wfnJd1x25u0sV22PZ3N70l4BN+4EFjE2hXjlWykJnpKcnfdx8qdsiQ9Ww3W1QO9W + NpkLqY96e4gL47c5KHaRblYyB9opCL2h6HkztATGiy1iHshFAbJBLUghHmENG1mA + xrccqozKVloWcgsSrLa0 + =y5Fb + -----END PGP MESSAGE----- + fp: B2D6D7BBEC03B2E66571C8C00AD18E16CFDEF700 + unencrypted_suffix: _unencrypted + version: 3.6.1 diff --git a/test/integration/secretssops.yaml b/test/integration/secretssops.yaml index a9f2ce6c..b778be7e 100644 --- a/test/integration/secretssops.yaml +++ b/test/integration/secretssops.yaml @@ -24,6 +24,9 @@ releases: - name: raw chart: center/incubator/raw version: 0.2.3 + secrets: + - secrets.yaml + - secrets_templated.yaml.gotmpl values: - templates: - | @@ -35,3 +38,5 @@ releases: key_1: {{ .Environment.Values.key_1 }} key_2: {{ .Environment.Values.key_2 }} key_shared: {{ .Environment.Values.key_shared }} + my_other_key: {{` {{ .Values.my_other_secret }} `}} + my_templated_key: {{` {{ .Values.my_templated_secret }} `}} diff --git a/test/integration/templates-golden/v2/httpbin/deployment.yaml b/test/integration/templates-golden/v2/httpbin/deployment.yaml index 3493d178..c902c48c 100644 --- a/test/integration/templates-golden/v2/httpbin/deployment.yaml +++ b/test/integration/templates-golden/v2/httpbin/deployment.yaml @@ -1,6 +1,6 @@ --- # Source: httpbin/templates/deployment.yaml -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: metadata: @@ -12,6 +12,9 @@ metadata: heritage: Tiller spec: replicas: 1 + selector: + matchLabels: + app: httpbin strategy: {} template: metadata: diff --git a/test/integration/templates-golden/v3/httpbin/deployment.yaml b/test/integration/templates-golden/v3/httpbin/deployment.yaml index 97ff6a02..9a7c0230 100644 --- a/test/integration/templates-golden/v3/httpbin/deployment.yaml +++ b/test/integration/templates-golden/v3/httpbin/deployment.yaml @@ -1,6 +1,6 @@ --- # Source: httpbin/templates/deployment.yaml -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: metadata: @@ -12,6 +12,9 @@ metadata: heritage: Helm spec: replicas: 1 + selector: + matchLabels: + app: httpbin strategy: {} template: metadata: