template_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package template
  13. import (
  14. "os"
  15. "strings"
  16. "testing"
  17. "github.com/google/go-cmp/cmp"
  18. "github.com/stretchr/testify/assert"
  19. corev1 "k8s.io/api/core/v1"
  20. v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. )
  22. const (
  23. pkcs12ContentNoPass = `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`
  24. pkcs12ContentWithPass = `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`
  25. pkcs12Cert = `-----BEGIN CERTIFICATE-----
  26. MIIDHTCCAgWgAwIBAgIRAKC4yxy9QGocND+6avTf7BgwDQYJKoZIhvcNAQELBQAw
  27. EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTAzMjAyMDA4MDhaFw0yMTAzMjAyMDM4
  28. MDhaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
  29. ggEKAoIBAQC3o6/JdZEqNbqNRkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4Nzj
  30. aG15owr92/11W0pxPUliRLti3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvW
  31. Y8jh8A0LQALZiV/9QsrJdXZdS47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE
  32. 1gEDqnKfRxXI8DEQKXr+CKPUwCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4e
  33. ugHe52vXHdh/HJ9VjNp0xOH1waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJa
  34. YOOonQSEswveSv6PcG9AHvpNPot2Xs6hAgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIC
  35. pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
  36. BBR00805mrpoonp95RmC3B6oLl+cGTAVBgNVHREEDjAMggpnb29ibGUuY29tMA0G
  37. CSqGSIb3DQEBCwUAA4IBAQAipc1b6JrEDayPjpz5GM5krcI8dCWVd8re0a9bGjjN
  38. ioWGlu/eTr5El0ffwCNZ2WLmL9rewfHf/bMvYz3ioFZJ2OTxfazqYXNggQz6cMfa
  39. lbedDCdt5XLVX2TyerGvFram+9Uyvk3l0uM7rZnwAmdirG4Tv94QRaD3q4xTj/c0
  40. mv+AggtK0aRFb9o47z/BypLdk5mhbf3Mmr88C8XBzEnfdYyf4JpTlZrYLBmDCu5d
  41. 9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
  42. QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
  43. -----END CERTIFICATE-----
  44. `
  45. pkcs12Key = `-----BEGIN PRIVATE KEY-----
  46. MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC3o6/JdZEqNbqN
  47. RkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4NzjaG15owr92/11W0pxPUliRLti
  48. 3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvWY8jh8A0LQALZiV/9QsrJdXZd
  49. S47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE1gEDqnKfRxXI8DEQKXr+CKPU
  50. wCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4eugHe52vXHdh/HJ9VjNp0xOH1
  51. waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJaYOOonQSEswveSv6PcG9AHvpN
  52. Pot2Xs6hAgMBAAECggEACTGPrmVNZDCWa1Y2hkJ0J7SoNcw+9O4M/jwMp4l/PD6P
  53. I98S78LYLCZhPLK17SmjUcnFO1AXKW1JeFS2D/fjfP256guvcqQNjLFoioxcOhVb
  54. ZGyd1Mi8JPqP5wfOj16gBeYDwTkjz9wqldcfiZaL9XoXetkZecbzR2JwC2FtIVuC
  55. 0njTjMNYpaBKnoLb8OTR0EQz7lYEo2MkQiWryz8wseONnFmdfh18p+p10YgCbuCH
  56. qesrWfDLLxaxZelNtDhDngg9LoCLmarYy7BgShacmUEgJTZ/x3xFC75thK3ln0OY
  57. +ktTgvVotYYaZi7qAjQiEsTvkTAPg5RMpQLd2UIWsQKBgQDCBp+1vURbwGzmTNUg
  58. HMipD6WDFdLc9DCacx6+ZqsEPTMWQbCpVZrDKiY0Rjt5F+xOCyMr00J5RDJXRC0G
  59. +L7NcJdywOFutT7vB+cmETg7l/6PHweNYBnE66706eTL/KVYZMi4tEinarPWhHmL
  60. jasfdLANtpDjdWkRt299TkPRbQKBgQDyS8Rr7KZdv04Csqkf+ASmiJpT5R6Y72kc
  61. 3XYpKETyB2FyPZkuh/zInMut9SkkSI9O/jA3zf956jj6sF1DHvp7T8KkIp5OAQeD
  62. J9AF65m2MnZfHFUeJ6ZQsggwMWqrD0ycIWP7YWtiBHH+D1wGkjYrssq+bvG/yNpA
  63. LtqdKq9lhQKBgQCZA2hIhy61vRckuEsLvCdzTGeW7UsR/XGnHEqOlaEhArKbRsrv
  64. gBdA+qiOaSTV5svw8E+YbE7sG6AnuhhYeyreEYEeeoZOLJmpIG5mUwYp2UBj1nC6
  65. SaOI7OVZOGu7g09SWokBQQxbG4cgEfFY4Sym7fs5lVTGTP3Dfwppo6NQMQKBgQCo
  66. J5NDP3Lafwk58BpV+H/pv8YzUUDh7M2rXbtCpxLqUdr8OOnVlEUISWFF8m5CIyVq
  67. MhjuscWLK9Wtjba7/YTjDaDM3sW05xv6lyfU5ATCoNTr/zLHgcb4HAZ4w+L+otiN
  68. RtMnxB2NYf5mzuwUF2cG/secUEzwyAlIH/xStSwTLQKBgQCRvqF+rqxnegoOgwVW
  69. qrWPv06wXD8dW2FlPpY5GXqA0l6erSK3YsQQToRmbem9ibPD7bd5P4gNbWfxwK4C
  70. Wt+1Rcb8OrDhDJbYz85bXBnPecKp4EN0b9SHO0/dsCqn2w30emc+9T/4m1ZDkpBd
  71. BixHvI/EJ8YK3ta5WdJWKC6hnA==
  72. -----END PRIVATE KEY-----
  73. `
  74. jwkPubRSA = `{"kid":"ex","kty":"RSA","key_ops":["sign","verify","wrapKey","unwrapKey","encrypt","decrypt"],"n":"p2VQo8qCfWAZmdWBVaYuYb-a-tWWm78K6Sr9poCvNcmv8rUPSLACxitQWR8gZaSH1DklVkqz-Ed8Cdlf8lkDg4Ex5tkB64jRdC1Uvn4CDpOH6cp-N2s8hTFLqy9_YaDmyQS7HiqthOi9oVjil1VMeWfaAbClGtFt6UnKD0Vb_DvLoWYQSqlhgBArFJi966b4E1pOq5Ad02K8pHBDThlIIx7unibLehhDU6q3DCwNH_OOLx6bgNtmvGYJDd1cywpkLQ3YzNCUPWnfMBJRP3iQP_WI21uP6cvo0DqBPBM4wvVzHbCT0vnIflwkbgEWkq1FprqAitZlop9KjLqzjp9vyQ","e":"AQAB"}`
  75. jwkPubRSAPKIX = `-----BEGIN PUBLIC KEY-----
  76. MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2VQo8qCfWAZmdWBVaYu
  77. Yb+a+tWWm78K6Sr9poCvNcmv8rUPSLACxitQWR8gZaSH1DklVkqz+Ed8Cdlf8lkD
  78. g4Ex5tkB64jRdC1Uvn4CDpOH6cp+N2s8hTFLqy9/YaDmyQS7HiqthOi9oVjil1VM
  79. eWfaAbClGtFt6UnKD0Vb/DvLoWYQSqlhgBArFJi966b4E1pOq5Ad02K8pHBDThlI
  80. Ix7unibLehhDU6q3DCwNH/OOLx6bgNtmvGYJDd1cywpkLQ3YzNCUPWnfMBJRP3iQ
  81. P/WI21uP6cvo0DqBPBM4wvVzHbCT0vnIflwkbgEWkq1FprqAitZlop9KjLqzjp9v
  82. yQIDAQAB
  83. -----END PUBLIC KEY-----
  84. `
  85. jwkPrivRSA = `{"kty" : "RSA","kid" : "cc34c0a0-bd5a-4a3c-a50d-a2a7db7643df","use" : "sig","n" : "pjdss8ZaDfEH6K6U7GeW2nxDqR4IP049fk1fK0lndimbMMVBdPv_hSpm8T8EtBDxrUdi1OHZfMhUixGaut-3nQ4GG9nM249oxhCtxqqNvEXrmQRGqczyLxuh-fKn9Fg--hS9UpazHpfVAFnB5aCfXoNhPuI8oByyFKMKaOVgHNqP5NBEqabiLftZD3W_lsFCPGuzr4Vp0YS7zS2hDYScC2oOMu4rGU1LcMZf39p3153Cq7bS2Xh6Y-vw5pwzFYZdjQxDn8x8BG3fJ6j8TGLXQsbKH1218_HcUJRvMwdpbUQG5nvA2GXVqLqdwp054Lzk9_B_f1lVrmOKuHjTNHq48w","e" : "AQAB","d" : "ksDmucdMJXkFGZxiomNHnroOZxe8AmDLDGO1vhs-POa5PZM7mtUPonxwjVmthmpbZzla-kg55OFfO7YcXhg-Hm2OWTKwm73_rLh3JavaHjvBqsVKuorX3V3RYkSro6HyYIzFJ1Ek7sLxbjDRcDOj4ievSX0oN9l-JZhaDYlPlci5uJsoqro_YrE0PRRWVhtGynd-_aWgQv1YzkfZuMD-hJtDi1Im2humOWxA4eZrFs9eG-whXcOvaSwO4sSGbS99ecQZHM2TcdXeAs1PvjVgQ_dKnZlGN3lTWoWfQP55Z7Tgt8Nf1q4ZAKd-NlMe-7iqCFfsnFwXjSiaOa2CRGZn-Q","p" : "4A5nU4ahEww7B65yuzmGeCUUi8ikWzv1C81pSyUKvKzu8CX41hp9J6oRaLGesKImYiuVQK47FhZ--wwfpRwHvSxtNU9qXb8ewo-BvadyO1eVrIk4tNV543QlSe7pQAoJGkxCia5rfznAE3InKF4JvIlchyqs0RQ8wx7lULqwnn0","q" : "ven83GM6SfrmO-TBHbjTk6JhP_3CMsIvmSdo4KrbQNvp4vHO3w1_0zJ3URkmkYGhz2tgPlfd7v1l2I6QkIh4Bumdj6FyFZEBpxjE4MpfdNVcNINvVj87cLyTRmIcaGxmfylY7QErP8GFA-k4UoH_eQmGKGK44TRzYj5hZYGWIC8","dp" : "lmmU_AG5SGxBhJqb8wxfNXDPJjf__i92BgJT2Vp4pskBbr5PGoyV0HbfUQVMnw977RONEurkR6O6gxZUeCclGt4kQlGZ-m0_XSWx13v9t9DIbheAtgVJ2mQyVDvK4m7aRYlEceFh0PsX8vYDS5o1txgPwb3oXkPTtrmbAGMUBpE","dq" : "mxRTU3QDyR2EnCv0Nl0TCF90oliJGAHR9HJmBe__EjuCBbwHfcT8OG3hWOv8vpzokQPRl5cQt3NckzX3fs6xlJN4Ai2Hh2zduKFVQ2p-AF2p6Yfahscjtq-GY9cB85NxLy2IXCC0PF--Sq9LOrTE9QV988SJy_yUrAjcZ5MmECk","qi" : "ldHXIrEmMZVaNwGzDF9WG8sHj2mOZmQpw9yrjLK9hAsmsNr5LTyqWAqJIYZSwPTYWhY4nu2O0EY9G9uYiqewXfCKw_UngrJt8Xwfq1Zruz0YY869zPN4GiE9-9rzdZB33RBw8kIOquY3MK74FMwCihYx_LiU2YTHkaoJ3ncvtvg"}`
  86. jwkPrivRSAPKCS8 = `-----BEGIN PRIVATE KEY-----
  87. MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQCmN2yzxloN8Qfo
  88. rpTsZ5bafEOpHgg/Tj1+TV8rSWd2KZswxUF0+/+FKmbxPwS0EPGtR2LU4dl8yFSL
  89. EZq637edDgYb2czbj2jGEK3Gqo28ReuZBEapzPIvG6H58qf0WD76FL1SlrMel9UA
  90. WcHloJ9eg2E+4jygHLIUowpo5WAc2o/k0ESppuIt+1kPdb+WwUI8a7OvhWnRhLvN
  91. LaENhJwLag4y7isZTUtwxl/f2nfXncKrttLZeHpj6/DmnDMVhl2NDEOfzHwEbd8n
  92. qPxMYtdCxsofXbXz8dxQlG8zB2ltRAbme8DYZdWoup3CnTngvOT38H9/WVWuY4q4
  93. eNM0erjzAgMBAAECggEBAJLA5rnHTCV5BRmcYqJjR566DmcXvAJgywxjtb4bPjzm
  94. uT2TO5rVD6J8cI1ZrYZqW2c5WvpIOeThXzu2HF4YPh5tjlkysJu9/6y4dyWr2h47
  95. warFSrqK191d0WJEq6Oh8mCMxSdRJO7C8W4w0XAzo+Inr0l9KDfZfiWYWg2JT5XI
  96. ubibKKq6P2KxND0UVlYbRsp3fv2loEL9WM5H2bjA/oSbQ4tSJtobpjlsQOHmaxbP
  97. XhvsIV3Dr2ksDuLEhm0vfXnEGRzNk3HV3gLNT741YEP3Sp2ZRjd5U1qFn0D+eWe0
  98. 4LfDX9auGQCnfjZTHvu4qghX7JxcF40omjmtgkRmZ/kCgYEA4A5nU4ahEww7B65y
  99. uzmGeCUUi8ikWzv1C81pSyUKvKzu8CX41hp9J6oRaLGesKImYiuVQK47FhZ++wwf
  100. pRwHvSxtNU9qXb8ewo+BvadyO1eVrIk4tNV543QlSe7pQAoJGkxCia5rfznAE3In
  101. KF4JvIlchyqs0RQ8wx7lULqwnn0CgYEAven83GM6SfrmO+TBHbjTk6JhP/3CMsIv
  102. mSdo4KrbQNvp4vHO3w1/0zJ3URkmkYGhz2tgPlfd7v1l2I6QkIh4Bumdj6FyFZEB
  103. pxjE4MpfdNVcNINvVj87cLyTRmIcaGxmfylY7QErP8GFA+k4UoH/eQmGKGK44TRz
  104. Yj5hZYGWIC8CgYEAlmmU/AG5SGxBhJqb8wxfNXDPJjf//i92BgJT2Vp4pskBbr5P
  105. GoyV0HbfUQVMnw977RONEurkR6O6gxZUeCclGt4kQlGZ+m0/XSWx13v9t9DIbheA
  106. tgVJ2mQyVDvK4m7aRYlEceFh0PsX8vYDS5o1txgPwb3oXkPTtrmbAGMUBpECgYEA
  107. mxRTU3QDyR2EnCv0Nl0TCF90oliJGAHR9HJmBe//EjuCBbwHfcT8OG3hWOv8vpzo
  108. kQPRl5cQt3NckzX3fs6xlJN4Ai2Hh2zduKFVQ2p+AF2p6Yfahscjtq+GY9cB85Nx
  109. Ly2IXCC0PF++Sq9LOrTE9QV988SJy/yUrAjcZ5MmECkCgYEAldHXIrEmMZVaNwGz
  110. DF9WG8sHj2mOZmQpw9yrjLK9hAsmsNr5LTyqWAqJIYZSwPTYWhY4nu2O0EY9G9uY
  111. iqewXfCKw/UngrJt8Xwfq1Zruz0YY869zPN4GiE9+9rzdZB33RBw8kIOquY3MK74
  112. FMwCihYx/LiU2YTHkaoJ3ncvtvg=
  113. -----END PRIVATE KEY-----
  114. `
  115. jwkPubEC = `{"kid":"https://kv-test-mj.vault.azure.net/keys/ec-p-521/e3d0e9c179b54988860c69c6ae172c65","kty":"EC","key_ops":["sign","verify"],"crv":"P-521","x":"AedOAtb7H7Oz1C_cPKI_R4CN_eai5nteY6KFW07FOoaqgQfVCSkQDK22fCOiMT_28c8LZYJRsiIFz_IIbQUW7bXj","y":"AOnchHnmBphIWXvanmMAmcCDkaED6ycW8GsAl9fQ43BMVZTqcTkJYn6vGnhn7MObizmkNSmgZYTwG-vZkIg03HHs"}`
  116. jwkPubECPKIX = `-----BEGIN PUBLIC KEY-----
  117. MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB504C1vsfs7PUL9w8oj9HgI395qLm
  118. e15jooVbTsU6hqqBB9UJKRAMrbZ8I6IxP/bxzwtlglGyIgXP8ghtBRbtteMA6dyE
  119. eeYGmEhZe9qeYwCZwIORoQPrJxbwawCX19DjcExVlOpxOQlifq8aeGfsw5uLOaQ1
  120. KaBlhPAb69mQiDTccew=
  121. -----END PUBLIC KEY-----
  122. `
  123. jwkPrivEC = `{"kty": "EC","kid": "rie3pHe8u8gjSa0IaJfqk7_iEfHeYfDYx-Bqi7vQc0s","crv": "P-256","x": "fDjg3Nq4jPf8IOZ0277aPVal_8iXySnzLUJAZghUzZM","y": "d863PeyBOK_Q4duiSmWwgIRzi1RPlFZTR-vACMlPg-Q","d": "jJs5xsoHUetdMabtt8H2KyX5T92nGul1chFeMT5hlr0"}`
  124. jwkPrivECPKCS8 = `-----BEGIN PRIVATE KEY-----
  125. MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjJs5xsoHUetdMabt
  126. t8H2KyX5T92nGul1chFeMT5hlr2hRANCAAR8OODc2riM9/wg5nTbvto9VqX/yJfJ
  127. KfMtQkBmCFTNk3fOtz3sgTiv0OHbokplsICEc4tUT5RWU0frwAjJT4Pk
  128. -----END PRIVATE KEY-----
  129. `
  130. )
  131. func TestExecute(t *testing.T) {
  132. tbl := []struct {
  133. name string
  134. tpl map[string][]byte
  135. labelsTpl map[string][]byte
  136. annotationsTpl map[string][]byte
  137. data map[string][]byte
  138. expetedData map[string][]byte
  139. expectedLabels map[string]string
  140. expectedAnnotations map[string]string
  141. expErr string
  142. }{
  143. {
  144. name: "test empty",
  145. tpl: nil,
  146. labelsTpl: nil,
  147. annotationsTpl: nil,
  148. data: nil,
  149. },
  150. {
  151. name: "b64dec func",
  152. tpl: map[string][]byte{
  153. "foo": []byte("{{ .secret | b64dec }}"),
  154. },
  155. data: map[string][]byte{
  156. "secret": []byte("MTIzNA=="),
  157. },
  158. expetedData: map[string][]byte{
  159. "foo": []byte("1234"),
  160. },
  161. },
  162. {
  163. name: "fromJson func",
  164. tpl: map[string][]byte{
  165. "foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo }}"),
  166. },
  167. data: map[string][]byte{
  168. "secret": []byte(`{"foo": "bar"}`),
  169. },
  170. expetedData: map[string][]byte{
  171. "foo": []byte("bar"),
  172. },
  173. },
  174. {
  175. name: "from & toJson func",
  176. tpl: map[string][]byte{
  177. "foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo | toJson }}"),
  178. },
  179. data: map[string][]byte{
  180. "secret": []byte(`{"foo": {"baz":"bang"}}`),
  181. },
  182. expetedData: map[string][]byte{
  183. "foo": []byte(`{"baz":"bang"}`),
  184. },
  185. },
  186. {
  187. name: "fromJson & toYaml func",
  188. tpl: map[string][]byte{
  189. "foo": []byte("{{ $var := .secret | fromJson | toYaml }}{{ $var }}"),
  190. },
  191. data: map[string][]byte{
  192. "secret": []byte(`{"foo": "bar"}`),
  193. },
  194. expetedData: map[string][]byte{
  195. "foo": []byte(`foo: bar`),
  196. },
  197. },
  198. {
  199. name: "fromYaml & toJson func",
  200. tpl: map[string][]byte{
  201. "foo": []byte("{{ $var := .secret | fromYaml | toJson }}{{ $var }}"),
  202. },
  203. data: map[string][]byte{
  204. "secret": []byte(`foo: bar`),
  205. },
  206. expetedData: map[string][]byte{
  207. "foo": []byte(`{"foo":"bar"}`),
  208. },
  209. },
  210. {
  211. name: "use sprig functions",
  212. tpl: map[string][]byte{
  213. "foo": []byte(`{{ .path | ext }}`),
  214. },
  215. data: map[string][]byte{
  216. "path": []byte(`foo/bar/baz.exe`),
  217. },
  218. expetedData: map[string][]byte{
  219. "foo": []byte(`.exe`),
  220. },
  221. },
  222. {
  223. name: "use replace function",
  224. tpl: map[string][]byte{
  225. "foo": []byte(`{{ .conn | replace "postgres://" "db+postgresql://"}}`),
  226. },
  227. data: map[string][]byte{
  228. "conn": []byte(`postgres://user:pass@db.host:5432/dbname`),
  229. },
  230. expetedData: map[string][]byte{
  231. "foo": []byte(`db+postgresql://user:pass@db.host:5432/dbname`),
  232. },
  233. },
  234. {
  235. name: "multiline template",
  236. tpl: map[string][]byte{
  237. "cfg": []byte(`
  238. datasources:
  239. - name: Graphite
  240. type: graphite
  241. access: proxy
  242. url: http://localhost:8080
  243. password: "{{ .password }}"
  244. user: "{{ .user }}"`),
  245. },
  246. data: map[string][]byte{
  247. "user": []byte(`foobert`),
  248. "password": []byte("harharhar"),
  249. },
  250. expetedData: map[string][]byte{
  251. "cfg": []byte(`
  252. datasources:
  253. - name: Graphite
  254. type: graphite
  255. access: proxy
  256. url: http://localhost:8080
  257. password: "harharhar"
  258. user: "foobert"`),
  259. },
  260. },
  261. {
  262. name: "base64 pipeline",
  263. tpl: map[string][]byte{
  264. "foo": []byte(`{{ "123412341234" | b64enc | b64dec }}`),
  265. },
  266. data: map[string][]byte{},
  267. expetedData: map[string][]byte{
  268. "foo": []byte("123412341234"),
  269. },
  270. },
  271. {
  272. name: "base64 pkcs12 extract",
  273. tpl: map[string][]byte{
  274. "key": []byte(`{{ .secret | b64dec | pkcs12key }}`),
  275. "cert": []byte(`{{ .secret | b64dec | pkcs12cert }}`),
  276. },
  277. data: map[string][]byte{
  278. "secret": []byte(pkcs12ContentNoPass),
  279. },
  280. expetedData: map[string][]byte{
  281. "key": []byte(pkcs12Key),
  282. "cert": []byte(pkcs12Cert),
  283. },
  284. },
  285. {
  286. name: "base64 pkcs12 extract with password",
  287. tpl: map[string][]byte{
  288. "key": []byte(`{{ .secret | b64dec | pkcs12keyPass "123456" }}`),
  289. "cert": []byte(`{{ .secret | b64dec | pkcs12certPass "123456" }}`),
  290. },
  291. data: map[string][]byte{
  292. "secret": []byte(pkcs12ContentWithPass),
  293. },
  294. expetedData: map[string][]byte{
  295. "key": []byte(pkcs12Key),
  296. "cert": []byte(pkcs12Cert),
  297. },
  298. },
  299. {
  300. name: "base64 decode error",
  301. tpl: map[string][]byte{
  302. "key": []byte(`{{ .example | b64dec }}`),
  303. },
  304. data: map[string][]byte{
  305. "example": []byte("iam_no_base64"),
  306. },
  307. expErr: "", // silent error
  308. },
  309. {
  310. name: "pkcs12 key wrong password",
  311. tpl: map[string][]byte{
  312. "key": []byte(`{{ .secret | b64dec | pkcs12keyPass "wrong" }}`),
  313. },
  314. data: map[string][]byte{
  315. "secret": []byte(pkcs12ContentWithPass),
  316. },
  317. expErr: "unable to decode pkcs12",
  318. },
  319. {
  320. name: "pkcs12 cert wrong password",
  321. tpl: map[string][]byte{
  322. "cert": []byte(`{{ .secret | b64dec | pkcs12certPass "wrong" }}`),
  323. },
  324. data: map[string][]byte{
  325. "secret": []byte(pkcs12ContentWithPass),
  326. },
  327. expErr: "unable to decode pkcs12",
  328. },
  329. {
  330. name: "fromJson error",
  331. tpl: map[string][]byte{
  332. "key": []byte(`{{ "{ # no json # }" | fromJson }}`),
  333. },
  334. data: map[string][]byte{},
  335. expErr: "", // silent error
  336. },
  337. {
  338. name: "template syntax error",
  339. tpl: map[string][]byte{
  340. "key": []byte(`{{ #xx }}`),
  341. },
  342. data: map[string][]byte{},
  343. expErr: "unable to parse template",
  344. },
  345. {
  346. name: "jwk rsa pub pem",
  347. tpl: map[string][]byte{
  348. "fn": []byte(`{{ .secret | jwkPublicKeyPem }}`),
  349. },
  350. data: map[string][]byte{
  351. "secret": []byte(jwkPubRSA),
  352. },
  353. expetedData: map[string][]byte{
  354. "fn": []byte(jwkPubRSAPKIX),
  355. },
  356. },
  357. {
  358. name: "jwk rsa priv pem",
  359. tpl: map[string][]byte{
  360. "fn": []byte(`{{ .secret | jwkPrivateKeyPem }}`),
  361. },
  362. data: map[string][]byte{
  363. "secret": []byte(jwkPrivRSA),
  364. },
  365. expetedData: map[string][]byte{
  366. "fn": []byte(jwkPrivRSAPKCS8),
  367. },
  368. },
  369. {
  370. name: "jwk ecdsa pub pem",
  371. tpl: map[string][]byte{
  372. "fn": []byte(`{{ .secret | jwkPublicKeyPem }}`),
  373. },
  374. data: map[string][]byte{
  375. "secret": []byte(jwkPubEC),
  376. },
  377. expetedData: map[string][]byte{
  378. "fn": []byte(jwkPubECPKIX),
  379. },
  380. },
  381. {
  382. name: "jwk ecdsa priv pem",
  383. tpl: map[string][]byte{
  384. "fn": []byte(`{{ .secret | jwkPrivateKeyPem }}`),
  385. },
  386. data: map[string][]byte{
  387. "secret": []byte(jwkPrivEC),
  388. },
  389. expetedData: map[string][]byte{
  390. "fn": []byte(jwkPrivECPKCS8),
  391. },
  392. },
  393. {
  394. name: "filter pem certificate",
  395. tpl: map[string][]byte{
  396. "fn": []byte(`{{ .secret | filterPEM "CERTIFICATE" }}`),
  397. },
  398. data: map[string][]byte{
  399. "secret": []byte(jwkPrivRSAPKCS8 + pkcs12Cert),
  400. },
  401. expetedData: map[string][]byte{
  402. "fn": []byte(pkcs12Cert),
  403. },
  404. },
  405. {
  406. name: "labels",
  407. tpl: map[string][]byte{
  408. "foo": []byte("{{ .secret | b64dec }}"),
  409. },
  410. labelsTpl: map[string][]byte{
  411. "bar": []byte("{{ .env | b64dec }}"),
  412. },
  413. data: map[string][]byte{
  414. "secret": []byte("MTIzNA=="),
  415. "env": []byte("ZGV2"),
  416. },
  417. expetedData: map[string][]byte{
  418. "foo": []byte("1234"),
  419. },
  420. expectedLabels: map[string]string{
  421. "bar": "dev",
  422. },
  423. },
  424. {
  425. name: "annotations",
  426. tpl: map[string][]byte{
  427. "foo": []byte("{{ .secret | b64dec }}"),
  428. },
  429. annotationsTpl: map[string][]byte{
  430. "bar": []byte("{{ .env | b64dec }}"),
  431. },
  432. data: map[string][]byte{
  433. "secret": []byte("MTIzNA=="),
  434. "env": []byte("ZGV2"),
  435. },
  436. expetedData: map[string][]byte{
  437. "foo": []byte("1234"),
  438. },
  439. expectedAnnotations: map[string]string{
  440. "bar": "dev",
  441. },
  442. },
  443. }
  444. for i := range tbl {
  445. row := tbl[i]
  446. t.Run(row.name, func(t *testing.T) {
  447. sec := &corev1.Secret{
  448. Data: make(map[string][]byte),
  449. ObjectMeta: v1.ObjectMeta{Labels: make(map[string]string), Annotations: make(map[string]string)},
  450. }
  451. err := Execute(row.tpl, row.labelsTpl, row.annotationsTpl, row.data, sec)
  452. if !ErrorContains(err, row.expErr) {
  453. t.Errorf("unexpected error: %s, expected: %s", err, row.expErr)
  454. }
  455. if row.expetedData == nil {
  456. return
  457. }
  458. assert.EqualValues(t, row.expetedData, sec.Data)
  459. if row.expectedLabels == nil {
  460. return
  461. }
  462. assert.EqualValues(t, row.expectedLabels, sec.ObjectMeta.Labels)
  463. if row.expectedAnnotations == nil {
  464. return
  465. }
  466. assert.EqualValues(t, row.expectedAnnotations, sec.ObjectMeta.Annotations)
  467. })
  468. }
  469. }
  470. func ErrorContains(out error, want string) bool {
  471. if out == nil {
  472. return want == ""
  473. }
  474. if want == "" {
  475. return false
  476. }
  477. return strings.Contains(out.Error(), want)
  478. }
  479. func TestPkcs12certPass(t *testing.T) {
  480. const (
  481. leafCertPath = "_testdata/foo.crt"
  482. intermediateCertPath = "_testdata/intermediate-ca.crt"
  483. rootCertPath = "_testdata/root-ca.crt"
  484. disjunctCertPath = "_testdata/disjunct-root-ca.crt"
  485. )
  486. type args struct {
  487. pass string
  488. filename string
  489. }
  490. type testCase struct {
  491. name string
  492. args args
  493. want []string
  494. wantErr bool
  495. }
  496. tests := []testCase{
  497. {
  498. // this case expects the whole chain to be stored
  499. // in a single bag.
  500. // bag(1): leaf/root/intermediate cert
  501. // bag(2): private key
  502. name: "read file without password",
  503. args: args{
  504. pass: "",
  505. filename: "_testdata/foo-nopass.pfx",
  506. },
  507. want: []string{
  508. // this order is important
  509. leafCertPath,
  510. intermediateCertPath,
  511. rootCertPath,
  512. },
  513. },
  514. {
  515. // same as above but with password
  516. name: "read file with password",
  517. args: args{
  518. pass: "1234",
  519. filename: "_testdata/foo-withpass-1234.pfx",
  520. },
  521. want: []string{
  522. // this order is important
  523. leafCertPath,
  524. intermediateCertPath,
  525. rootCertPath,
  526. },
  527. },
  528. {
  529. // cert chain may be stored in different bags
  530. // this test case uses a pfx that has the following structure:
  531. // bag(1): leaf certificate
  532. // bag(2): root + intermediate cert
  533. // bag(3): private key
  534. name: "read multibag cert chain",
  535. args: args{
  536. pass: "",
  537. filename: "_testdata/foo-multibag-nopass.pfx",
  538. },
  539. want: []string{
  540. // this order is important
  541. leafCertPath,
  542. intermediateCertPath,
  543. rootCertPath,
  544. },
  545. },
  546. {
  547. // cert chain may contain a disjunct cert
  548. // bag(1): leaf/root/intermediate/disjunct
  549. // bag(2): private key
  550. name: "read disjunct cert chain",
  551. args: args{
  552. pass: "",
  553. filename: "_testdata/foo-disjunct-nopass.pfx",
  554. },
  555. want: []string{
  556. // this order is important
  557. leafCertPath,
  558. rootCertPath,
  559. intermediateCertPath,
  560. disjunctCertPath,
  561. },
  562. },
  563. {
  564. name: "read file wrong password",
  565. args: args{
  566. pass: "wrongpass",
  567. filename: "_testdata/foo-withpass-1234.pfx",
  568. },
  569. wantErr: true,
  570. },
  571. }
  572. testFunc := func(t *testing.T, tc testCase) {
  573. archive, err := os.ReadFile(tc.args.filename)
  574. if err != nil {
  575. t.Error(err)
  576. }
  577. var expOut []byte
  578. for _, w := range tc.want {
  579. c, err := os.ReadFile(w)
  580. if err != nil {
  581. t.Error(err)
  582. }
  583. expOut = append(expOut, c...)
  584. }
  585. got, err := pkcs12certPass(tc.args.pass, string(archive))
  586. if (err != nil) != tc.wantErr {
  587. t.Errorf("pkcs12certPass() error = %v, wantErr %v", err, tc.wantErr)
  588. return
  589. }
  590. if diff := cmp.Diff(string(expOut), got); diff != "" {
  591. t.Errorf("pkcs12certPass() = diff:\n%s", diff)
  592. }
  593. }
  594. for _, tt := range tests {
  595. t.Run(tt.name, func(t *testing.T) {
  596. testFunc(t, tt)
  597. })
  598. }
  599. }