template_test.go 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  1. /*
  2. Copyright © The ESO Authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package template
  14. import (
  15. "crypto/rand"
  16. "crypto/rsa"
  17. "crypto/x509"
  18. "encoding/pem"
  19. "os"
  20. "strings"
  21. "testing"
  22. "github.com/google/go-cmp/cmp"
  23. "github.com/stretchr/testify/assert"
  24. "github.com/stretchr/testify/require"
  25. corev1 "k8s.io/api/core/v1"
  26. v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
  28. esapi "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  29. )
  30. const (
  31. pkcs12ContentNoPass = `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`
  32. pkcs12ContentWithPass = `MIIJYQIBAzCCCScGCSqGSIb3DQEHAaCCCRgEggkUMIIJEDCCA8cGCSqGSIb3DQEHBqCCA7gwggO0AgEAMIIDrQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQI2eZRJ7Ar+JQCAggAgIIDgFTbOtkFPjqxAoYRHoq1SbyXKf/NRbBA5AqxQlv9aFVT4VcxUSrMGaSWifX2UjsVWQzn134yoLLbdJ0jTorVD+EuBUmtb3xXbBwLqtFZxwcWodYA5WhPQdDcQo0cD3o1vrsXPQARQR6ISSFnhFjPYdH9cO2LqUKV5pjFhIs2/1VPDS2eY7SWZN52DK3QknSj23S3ZW2s4TFEj/5C4ssbO7cWNWBjjaORnd17FMNgVtcRw8ITmLdGBOpFUwP8wIdiLGrXiyjfMLns74nztRelV30/v0DPlz0pZtOPygi/dy0qpbil3wtOFrtQBLEdvLNmt9ikQgGs3pJBS68eMJLu3jAU6rCIKycq0+E0eMXeHcseyMwgguTj2h4t+E4S7nU11lViBFqkSBKxE28+9fNlPvCsZ4WhQZ6TAW3E/jDy/ZSqmak5V7/khMlRPvtrxz71ivksH0iipPdJJkGi7SDEvETySBETiqIslUmsF0ZYeHR5wIBkB5V8zmi8RRZtpvDGbzuQ22V6sNk2mTDh+BRus7gNCoSGWYXWqNNp1PnznuYCJp9T+0mObcAijE7IQuhpYMeQPF+MUIlG5lmpNouzuygTf++xrKIjzP36DcthnMPeD/8LYWfzkuAeRodjl7Z1G6XLvBD5h+Xlq23WPjMcXUiiWYXxTREAQ1EWUf4A9twGcxHJ5AatbvQY3QUoS4a7LNuy17lF7G+O1SFDtGeHZXHHecaVpuAtqZEYeUpqy6ZzMJXtXE1JNl/UR9TtTordb1V5Pf45JTYKLI+SwxVQbRiTgfhulNc+E3tV1AEELZt4CKmh1OFJoJRtyREMfdVuP4rx7ywIoMYuWw8CRqJ3qSmdwz2kmL2pfJNn6vDfN6rNa+sXWErOJ7naSAKQH2CJfnkCOFxkKfwjbOcNRbnGKah8NyWu6xqlv7Y4xEJYqmPahGHmrSfdAt3mpc5zD74DvetLIczcadKaLH7mp6h98xHayvXh0UE7ERHeskfSPrLxL9A3V1RZXDOtcZFWSKHzokuXMDF9OnrcMYDzYgtzof4ReY2t1ldGF7phYINhDlUNyhzyjwyWQbdkxr/+FtWq8Sbm7o2zMTby48c25gnqD9U8RTAO+bY3oV3dQ4bpAOzWdzVmFjESUFx0xVwbTSJGXdkH4YmD5He+xwxTa0Je0HE5+ui5dbP1gxUY+pCGLOhGMIIFQQYJKoZIhvcNAQcBoIIFMgSCBS4wggUqMIIFJgYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECGYAccNFWW6kAgIIAASCBMgbXw69iyx73RGWS3FYeuvF5L1VWXQGrDLdUGwa3SdovXxmP1pKBAb82UuiydXDpKSVCmefeEQTs6ucEFRmXrDIldNanqUwbydy3GSJ+4iNsVQHbFgNppH4e90L7BlLcZ3MzSrVEwxWVMHq+XLqTKf3X3QyrmA3mmF96+Nd+icpDIktd+/h2BHnSXHNP0QfVH27H4DwbMDijttXY0JB+8qP9m25Wn4zkmOPEUhrY4Ptv2I08eHFAuNI0jWUwfRhC4FDbUdwFb0aZjA3Te6uYTsu2zAlmg9HuqsD/Ef/wkBEKZLBkjiXa/niFVrwELXhWZDPBAuo+/1UbzXglsW4QDU4LbUutcs6DLag1vLe40a2LO1ODQm7Zw0bxLkb3f/ry6ZFYvO78XmHo4c/oQf4KPUtM2bLz5q7uOxAx07vHYaU2BVt3NjgiIO5VVKjw0075GdgFxwPvYncv1fsC5jSIkX43GuzEtoBTpJKDYb2nhKbN9XWixwGOhUBTK3WYBhn+uaMJs4l3EgkDtK9tsUs5VQQHawj0WrGS1mQhaBfcyZzv4wSn0d3JUO2CN0e9EReJcQvsEnwUvohilOvjDHHhTq8Kp4XU4jbq7TAKqxs3TOmdoskRykn9oKUPExJVhJQonFT3ietV5BHrnN/QoDCSeOR80ZxvWHrQDz3Hm1ygiHd8LYmN4IjiD8b28ZrCALifWxh0WmIYtLZrUjMZavPh+caWH9IG32fTxV9b1bgJD8vWqscj9jCjeMJvkKQo8PFg1kMAxt1u+bIyktTq42O9qxwGrdqEMeBzXxDJMMaRIH3m9LNZ/P5Nk4/hMURhCZJtRtNfOVTK+Q6kKgsdK2EHcuEnp/qBefZjve+xmitbF1W7C4+B7b2JNBacdIm1nE56DwglT/IUk65JrNFP3rf4c5ic76LCQrvyfLiKCGaqcihM9siLVFPYdrnr8TlGbCFnGbpBqMQA5MtZQaDUug50PJtdxlgfwWH4qliimgchCaZbSTcgN5YTguSe16uUSusHD+r6XdtI0939uDILXJjQMczhIKNw8w0Tn4Z3/g2KlB6cwbtaglnnO4a/USh0cPC1a581byNqeFoMi+mAhqfKkwdDuti4GX7OrhkUOkiRjEUXdcckpmmIsyamH/g1dq3CNFXFNIgRRrzIDo4Opr3Ip2VE/4BDQoo/+Rybzxh8bsHgCEujQf8urGxjGyd2ulHoXzHWhz7pPPuY5UN6dC9WZmOQDVous/1nhYThoLVVc61Rk6d83+Ac7iRg4bY5q/73J4HvPMmrTOOOqqn3wc9Pe5ibEy4tFaYnim4p1ZRm8YcwosZmuFPdsP6G5l5qt6uOyr2+qNpXIBkDpG7I6Ls10O7L3PQAX9zRGfcz6Ds0KtuDrLpaVvhuXpewsBwpo1lmhv9bAa4ppBuWznmKigX+vYojSxd/eCRAtMs+Lx6ppZsYNVhbdEIGKXSGwG98sSTZkoLHBMkUW7S8jpeSCHZWEFBUOPJQzAr5cW1w+RAs33cGUygZ5XEEx4DeW8MnO4lCuP+VDOwu3TAKhzAD+qCyXbLEzWiyL5fq3XL+YJtoAc8Mra9lK6jDqzq4u+PLNoYY+kWTBhCyRZ+PfzcXLry8pxuP5E6VtRgfYcxJTAjBgkqhkiG9w0BCRUxFgQUOEXV6IFYGpCSHi0MPHz4b3W0KOQwMTAhMAkGBSsOAwIaBQAEFBa+SV9FU2UObo+nYKdyt/kZVw6FBAgey4GonFtJ2gICCAA=`
  33. pkcs12Cert = `-----BEGIN CERTIFICATE-----
  34. MIIDHTCCAgWgAwIBAgIRAKC4yxy9QGocND+6avTf7BgwDQYJKoZIhvcNAQELBQAw
  35. EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTAzMjAyMDA4MDhaFw0yMTAzMjAyMDM4
  36. MDhaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
  37. ggEKAoIBAQC3o6/JdZEqNbqNRkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4Nzj
  38. aG15owr92/11W0pxPUliRLti3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvW
  39. Y8jh8A0LQALZiV/9QsrJdXZdS47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE
  40. 1gEDqnKfRxXI8DEQKXr+CKPUwCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4e
  41. ugHe52vXHdh/HJ9VjNp0xOH1waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJa
  42. YOOonQSEswveSv6PcG9AHvpNPot2Xs6hAgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIC
  43. pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
  44. BBR00805mrpoonp95RmC3B6oLl+cGTAVBgNVHREEDjAMggpnb29ibGUuY29tMA0G
  45. CSqGSIb3DQEBCwUAA4IBAQAipc1b6JrEDayPjpz5GM5krcI8dCWVd8re0a9bGjjN
  46. ioWGlu/eTr5El0ffwCNZ2WLmL9rewfHf/bMvYz3ioFZJ2OTxfazqYXNggQz6cMfa
  47. lbedDCdt5XLVX2TyerGvFram+9Uyvk3l0uM7rZnwAmdirG4Tv94QRaD3q4xTj/c0
  48. mv+AggtK0aRFb9o47z/BypLdk5mhbf3Mmr88C8XBzEnfdYyf4JpTlZrYLBmDCu5d
  49. 9RLLsjXxhag8xqMtd1uLUM8XOTGzVWacw8iGY+CTtBKqyA+AE6/bDwZvEwVtsKtC
  50. QJ85ioEpy00NioqcF0WyMZH80uMsPycfpnl5uF7RkW8u
  51. -----END CERTIFICATE-----
  52. `
  53. pkcs12Key = `-----BEGIN PRIVATE KEY-----
  54. MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC3o6/JdZEqNbqN
  55. RkopHhJtJG5c4qS5d0tQ/kZYpfD/v/izAYum4NzjaG15owr92/11W0pxPUliRLti
  56. 3y6iScTs+ofm2D7p4UXj/Fnho/2xoWSOoWAodgvWY8jh8A0LQALZiV/9QsrJdXZd
  57. S47DYZLsQ3z9yFC/CdXkg1l7AQ3fIVGKdrQBr9kE1gEDqnKfRxXI8DEQKXr+CKPU
  58. wCAytegmy0SHp53zNAvY+kopHytzmJpXLoEhxq4eugHe52vXHdh/HJ9VjNp0xOH1
  59. waAgAGxHlltCW0PVd5AJ0SXROBS/a3V9sZCbCrJaYOOonQSEswveSv6PcG9AHvpN
  60. Pot2Xs6hAgMBAAECggEACTGPrmVNZDCWa1Y2hkJ0J7SoNcw+9O4M/jwMp4l/PD6P
  61. I98S78LYLCZhPLK17SmjUcnFO1AXKW1JeFS2D/fjfP256guvcqQNjLFoioxcOhVb
  62. ZGyd1Mi8JPqP5wfOj16gBeYDwTkjz9wqldcfiZaL9XoXetkZecbzR2JwC2FtIVuC
  63. 0njTjMNYpaBKnoLb8OTR0EQz7lYEo2MkQiWryz8wseONnFmdfh18p+p10YgCbuCH
  64. qesrWfDLLxaxZelNtDhDngg9LoCLmarYy7BgShacmUEgJTZ/x3xFC75thK3ln0OY
  65. +ktTgvVotYYaZi7qAjQiEsTvkTAPg5RMpQLd2UIWsQKBgQDCBp+1vURbwGzmTNUg
  66. HMipD6WDFdLc9DCacx6+ZqsEPTMWQbCpVZrDKiY0Rjt5F+xOCyMr00J5RDJXRC0G
  67. +L7NcJdywOFutT7vB+cmETg7l/6PHweNYBnE66706eTL/KVYZMi4tEinarPWhHmL
  68. jasfdLANtpDjdWkRt299TkPRbQKBgQDyS8Rr7KZdv04Csqkf+ASmiJpT5R6Y72kc
  69. 3XYpKETyB2FyPZkuh/zInMut9SkkSI9O/jA3zf956jj6sF1DHvp7T8KkIp5OAQeD
  70. J9AF65m2MnZfHFUeJ6ZQsggwMWqrD0ycIWP7YWtiBHH+D1wGkjYrssq+bvG/yNpA
  71. LtqdKq9lhQKBgQCZA2hIhy61vRckuEsLvCdzTGeW7UsR/XGnHEqOlaEhArKbRsrv
  72. gBdA+qiOaSTV5svw8E+YbE7sG6AnuhhYeyreEYEeeoZOLJmpIG5mUwYp2UBj1nC6
  73. SaOI7OVZOGu7g09SWokBQQxbG4cgEfFY4Sym7fs5lVTGTP3Dfwppo6NQMQKBgQCo
  74. J5NDP3Lafwk58BpV+H/pv8YzUUDh7M2rXbtCpxLqUdr8OOnVlEUISWFF8m5CIyVq
  75. MhjuscWLK9Wtjba7/YTjDaDM3sW05xv6lyfU5ATCoNTr/zLHgcb4HAZ4w+L+otiN
  76. RtMnxB2NYf5mzuwUF2cG/secUEzwyAlIH/xStSwTLQKBgQCRvqF+rqxnegoOgwVW
  77. qrWPv06wXD8dW2FlPpY5GXqA0l6erSK3YsQQToRmbem9ibPD7bd5P4gNbWfxwK4C
  78. Wt+1Rcb8OrDhDJbYz85bXBnPecKp4EN0b9SHO0/dsCqn2w30emc+9T/4m1ZDkpBd
  79. BixHvI/EJ8YK3ta5WdJWKC6hnA==
  80. -----END PRIVATE KEY-----
  81. `
  82. 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"}`
  83. jwkPubRSAPKIX = `-----BEGIN PUBLIC KEY-----
  84. MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2VQo8qCfWAZmdWBVaYu
  85. Yb+a+tWWm78K6Sr9poCvNcmv8rUPSLACxitQWR8gZaSH1DklVkqz+Ed8Cdlf8lkD
  86. g4Ex5tkB64jRdC1Uvn4CDpOH6cp+N2s8hTFLqy9/YaDmyQS7HiqthOi9oVjil1VM
  87. eWfaAbClGtFt6UnKD0Vb/DvLoWYQSqlhgBArFJi966b4E1pOq5Ad02K8pHBDThlI
  88. Ix7unibLehhDU6q3DCwNH/OOLx6bgNtmvGYJDd1cywpkLQ3YzNCUPWnfMBJRP3iQ
  89. P/WI21uP6cvo0DqBPBM4wvVzHbCT0vnIflwkbgEWkq1FprqAitZlop9KjLqzjp9v
  90. yQIDAQAB
  91. -----END PUBLIC KEY-----
  92. `
  93. 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"}`
  94. jwkPrivRSAPKCS8 = `-----BEGIN PRIVATE KEY-----
  95. MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQCmN2yzxloN8Qfo
  96. rpTsZ5bafEOpHgg/Tj1+TV8rSWd2KZswxUF0+/+FKmbxPwS0EPGtR2LU4dl8yFSL
  97. EZq637edDgYb2czbj2jGEK3Gqo28ReuZBEapzPIvG6H58qf0WD76FL1SlrMel9UA
  98. WcHloJ9eg2E+4jygHLIUowpo5WAc2o/k0ESppuIt+1kPdb+WwUI8a7OvhWnRhLvN
  99. LaENhJwLag4y7isZTUtwxl/f2nfXncKrttLZeHpj6/DmnDMVhl2NDEOfzHwEbd8n
  100. qPxMYtdCxsofXbXz8dxQlG8zB2ltRAbme8DYZdWoup3CnTngvOT38H9/WVWuY4q4
  101. eNM0erjzAgMBAAECggEBAJLA5rnHTCV5BRmcYqJjR566DmcXvAJgywxjtb4bPjzm
  102. uT2TO5rVD6J8cI1ZrYZqW2c5WvpIOeThXzu2HF4YPh5tjlkysJu9/6y4dyWr2h47
  103. warFSrqK191d0WJEq6Oh8mCMxSdRJO7C8W4w0XAzo+Inr0l9KDfZfiWYWg2JT5XI
  104. ubibKKq6P2KxND0UVlYbRsp3fv2loEL9WM5H2bjA/oSbQ4tSJtobpjlsQOHmaxbP
  105. XhvsIV3Dr2ksDuLEhm0vfXnEGRzNk3HV3gLNT741YEP3Sp2ZRjd5U1qFn0D+eWe0
  106. 4LfDX9auGQCnfjZTHvu4qghX7JxcF40omjmtgkRmZ/kCgYEA4A5nU4ahEww7B65y
  107. uzmGeCUUi8ikWzv1C81pSyUKvKzu8CX41hp9J6oRaLGesKImYiuVQK47FhZ++wwf
  108. pRwHvSxtNU9qXb8ewo+BvadyO1eVrIk4tNV543QlSe7pQAoJGkxCia5rfznAE3In
  109. KF4JvIlchyqs0RQ8wx7lULqwnn0CgYEAven83GM6SfrmO+TBHbjTk6JhP/3CMsIv
  110. mSdo4KrbQNvp4vHO3w1/0zJ3URkmkYGhz2tgPlfd7v1l2I6QkIh4Bumdj6FyFZEB
  111. pxjE4MpfdNVcNINvVj87cLyTRmIcaGxmfylY7QErP8GFA+k4UoH/eQmGKGK44TRz
  112. Yj5hZYGWIC8CgYEAlmmU/AG5SGxBhJqb8wxfNXDPJjf//i92BgJT2Vp4pskBbr5P
  113. GoyV0HbfUQVMnw977RONEurkR6O6gxZUeCclGt4kQlGZ+m0/XSWx13v9t9DIbheA
  114. tgVJ2mQyVDvK4m7aRYlEceFh0PsX8vYDS5o1txgPwb3oXkPTtrmbAGMUBpECgYEA
  115. mxRTU3QDyR2EnCv0Nl0TCF90oliJGAHR9HJmBe//EjuCBbwHfcT8OG3hWOv8vpzo
  116. kQPRl5cQt3NckzX3fs6xlJN4Ai2Hh2zduKFVQ2p+AF2p6Yfahscjtq+GY9cB85Nx
  117. Ly2IXCC0PF++Sq9LOrTE9QV988SJy/yUrAjcZ5MmECkCgYEAldHXIrEmMZVaNwGz
  118. DF9WG8sHj2mOZmQpw9yrjLK9hAsmsNr5LTyqWAqJIYZSwPTYWhY4nu2O0EY9G9uY
  119. iqewXfCKw/UngrJt8Xwfq1Zruz0YY869zPN4GiE9+9rzdZB33RBw8kIOquY3MK74
  120. FMwCihYx/LiU2YTHkaoJ3ncvtvg=
  121. -----END PRIVATE KEY-----
  122. `
  123. 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"}`
  124. jwkPubECPKIX = `-----BEGIN PUBLIC KEY-----
  125. MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB504C1vsfs7PUL9w8oj9HgI395qLm
  126. e15jooVbTsU6hqqBB9UJKRAMrbZ8I6IxP/bxzwtlglGyIgXP8ghtBRbtteMA6dyE
  127. eeYGmEhZe9qeYwCZwIORoQPrJxbwawCX19DjcExVlOpxOQlifq8aeGfsw5uLOaQ1
  128. KaBlhPAb69mQiDTccew=
  129. -----END PUBLIC KEY-----
  130. `
  131. jwkPrivEC = `{"kty": "EC","kid": "rie3pHe8u8gjSa0IaJfqk7_iEfHeYfDYx-Bqi7vQc0s","crv": "P-256","x": "fDjg3Nq4jPf8IOZ0277aPVal_8iXySnzLUJAZghUzZM","y": "d863PeyBOK_Q4duiSmWwgIRzi1RPlFZTR-vACMlPg-Q","d": "jJs5xsoHUetdMabtt8H2KyX5T92nGul1chFeMT5hlr0"}`
  132. jwkPrivECPKCS8 = `-----BEGIN PRIVATE KEY-----
  133. MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjJs5xsoHUetdMabt
  134. t8H2KyX5T92nGul1chFeMT5hlr2hRANCAAR8OODc2riM9/wg5nTbvto9VqX/yJfJ
  135. KfMtQkBmCFTNk3fOtz3sgTiv0OHbokplsICEc4tUT5RWU0frwAjJT4Pk
  136. -----END PRIVATE KEY-----
  137. `
  138. rsaDecryptPKRSAPKCS8 = `-----BEGIN PRIVATE KEY-----
  139. MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChzs1R+jA3Goqi
  140. ropPzF4Ehpbi6VklbeZWP+RoU3rJshONJO6w9tPhbp0YIXrPSM9P5a9xaaNxDR9e
  141. u84O05+vq3C4P9I0jb5GSjiuznrmsprFWGaGdd4Vr7Fir1oqfeVc+znQFUCvkq7B
  142. EWobOonl6ktQ2OHBK0bEzXB7qY7P4ETI6owDUL+pkAwHzdnwk4sXMDKBLT3WZVRn
  143. xPppIJ4VAEph1fJOCIIskxVBh8cAT4QRxsdu8oB7cAuYJLBBKiS/GGIA7vh9sQrb
  144. +0BAgLqvy+kiQeQhYgF/Y/uVwkgAphFzSjSjoSFQ50nNE2VJA5J6o7QZ413DlIWr
  145. VJKNZJDbAgMBAAECggEAemklU5te1pExyJka8fu+NNZNWCUI2BQoaZ+0gGiHQAeE
  146. WwdRvHc/HBC+r/7EFgUTMXKmI7qzd1diIB0caoMXD6M3h2xg7nk9NZf5AeYbfGQq
  147. SpnyFk8dUHK2U94s7HCKEKnOtukdIrZplo5CI49Ju7JggC1TvPuscj6pliRUclYY
  148. Pc6pTVaG+bludDR8YkQ1mGi04wMQHpnisegRpMSjt9uZc1jKM7SSaHggu4/vuewo
  149. CFdra50/MjidIOXd5T5iVYY28J+gR8oCCKySTogNJ3JpNMNAW4FHfime5B+uS0IA
  150. YI/N8yjT/BPgRt4lQpR+6zi3fpguWNIM71xye1/R4QKBgQDNZNGFOntbFM2NTPYu
  151. 4APRVu4a0gM+JEA/ozuxTigkgaj6dNeJvaNTxcKG0MmGxQLEcvgCDaWIoM6Qrj1K
  152. YVwdiv1MddRDdSHQjGjNM6n7jNfYVQ2gP+1wDwTMN+eyAW8KoZByaQimmjyBj/Ps
  153. C8VWPxyrw/UeHqzTazyEIZ2fHQKBgQDJrM2/xx7F63C6GaW+5gMeColxkdYb29Aw
  154. R3xb2rn5lVPLW0BORQQuepZuaI+ZLTb4Op7V4yAC/S9femFXpgkZa56aacwy1jxb
  155. R9WO0CWP3QCUCcIBF/4lbJDZ6gQLr51oahXhhjbgGMrlguC/j4R9n3i58EaeukeE
  156. +Hsu/hMWVwKBgETsWALFJS/jQzbvZI1GTwGoki4d20i3EXhJZnaRK5dUi0fAfbOT
  157. F4O9ERH8biPzaIJTsjW+LpYyoB6c2aRkF20yft1xjNE2NSquc1yowZnQIX5OzEvC
  158. KAM6hvmgqPdq08BVhwtdg7GkgDlZ/Rhwur++XfilwVNiJ8yqZ5xPS31hAoGBALnu
  159. hB5MMPXd86bPoHyYSMV4h3DaOGCkzpLERUXWKOGOp5tzfJzsikdjo68U3VcmVWiT
  160. ev7MkCXRUMyg4n/RRtBV5PqNkcJIu4qYdq5c/lRdN3xEZsVlXl0Yc49EbghsFx49
  161. uACdIZiHov/oItbZNRgwXzhl6mXKbceM4tzXR7evAoGBALug2beVoVAl2nAB2RkQ
  162. Jy3viDKO+C6Z82gsS5x9Wif9cJTppIarZC+t7w33f4WHJiYT1VDxse08dohC5Nn7
  163. 7WWKdtLMSyUaXE46s37Kl5tkTkROj3wBzSIzwLYAwsthcpQVubwDAMsig8EUAdr/
  164. 0IwaauEPX9lBYMZDMYuSAR5n
  165. -----END PRIVATE KEY-----
  166. `
  167. rsaDecryptDataPKCS8Base64 = `hAZJktRFdzSkGxxiiSE46T271veCgwvC0GrY+AwDYA/KeuFZFdPgZsJ74awu1WR6x4BrbMLTXNpQw4UqChdbaM7VoKUCkPTcCU1jsveqYNisM2MNF98QjNjvp+9jXHfAsClLA5AvJxe3GjfWIi18E4PieFpATn/BTrmoklx4rSkWmfifZol7Wcny0D2fhrj/JOdxEIqowUB/tNwYzNd+lXgm55wea+G3YnD3Fr4ARaCCaQMUcdW9Kgx7mmZGZE3xDAhs8WMfpe9xVZ17Ca7Sw2r1JKS0o0fYiZNHUmCXVsP9O+//+0sfEtETiVUF0jItrwlK4GL8+bVcXQ9N2TW7+g==`
  168. rsaDecryptPKRSAPKCS1 = `-----BEGIN RSA PRIVATE KEY-----
  169. MIICXAIBAAKBgQC8ronsBTX6GD5YhoE/v76+ZkWX0gODzAD+aCYIyTs4PiWruxlV
  170. SOtjwq2gRgUexE5Hsz8cxhFz5Db8qFXBsA+GgXjByQuVbBw04SCKHgc0zhbcWonV
  171. 3Rk03pjVB1HfuxcDRja8JZontfMAJyPNJovPu3rIi8npSC+T5g7Fq9UCbQIDAQAB
  172. AoGAAo2+MiKT63GejmYro6g9taf+syJVh9gf/1F7ikzm70jwC5X5rszQ2sXMwcmQ
  173. 0izH/nJvnT0VCWOCVwMUPg3a9+odoMNFyg2u3XCLBNr3vlgG3xeCTdjzaMnY61ct
  174. xU4JgpIuiAlwCqhNfKuHxeesM/cvh9eC11ELXh27gLsNCEECQQDng5klIGPLHfiN
  175. 3wam6wxLnqHPuhXAyrOAKA1qBlZGKI6n6iBYpfN+Y70gt10f3SBlFfkSyF7uZsUy
  176. maofmjARAkEA0KM6Rj+p2CRMFMh4NpON4RKaQIYNGMTpe/akYBOx6wcZy0saON9l
  177. eHS3nq77TDT+mA3uDbu+6VD8j8eEcXUInQJAYJkfQEd4fBrAR+nj66etVKwW1gbN
  178. 5shtBy8vEasdOl7XzyY4YuSzaWwSUOFRYOcyChuV9olWWuDUrR1Cx7bdEQJBALzY
  179. gg7D4UA62oKVUfpUZL+szuJIc+JPmecSwIYWTZymuLpCKGICEx6Mxwdi6yN3dFq9
  180. gRP9NDiLjY+20DLB9CECQB5IqCvT396rjJn3g6sRXHX5qApJwInofLByafcjGd34
  181. ejJKh20FmJegJhkImmNTokNbQZbYiLAP07Ykx9A8jLg=
  182. -----END RSA PRIVATE KEY-----
  183. `
  184. rsaDecryptDataPKCS1Base64 = `Xd9Jij8+hTqM7ii1nnKbKZy7pHhn3BJwxrENwIlvf0iRysVKn7gmAaD6UV4EpNwYOHvLbo6yLWBme6msVAhIV9KOp22jDe9j837C48rcUiF93Jb7+plabbwTQt4iqi1EKxEfVvKi4tLsLBRhu0v583oQAfCf5aLwF3Vb5bPgGeY=`
  185. rsaDecryptPubKeyRSAPKCS1 = `-----BEGIN PUBLIC KEY-----
  186. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ronsBTX6GD5YhoE/v76+ZkWX
  187. 0gODzAD+aCYIyTs4PiWruxlVSOtjwq2gRgUexE5Hsz8cxhFz5Db8qFXBsA+GgXjB
  188. yQuVbBw04SCKHgc0zhbcWonV3Rk03pjVB1HfuxcDRja8JZontfMAJyPNJovPu3rI
  189. i8npSC+T5g7Fq9UCbQIDAQAB
  190. -----END PUBLIC KEY-----
  191. `
  192. )
  193. func rsaEncryptOAEP(t testing.TB, publicKeyPEM []byte, hash, plaintext string) []byte {
  194. t.Helper()
  195. block, _ := pem.Decode(publicKeyPEM)
  196. if block == nil || block.Type != "PUBLIC KEY" {
  197. t.Fatalf("failed to decode PEM block containing public key")
  198. }
  199. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  200. if err != nil {
  201. t.Fatalf("failed to parse DER encoded public key: %v", err)
  202. }
  203. rsaPub, ok := pub.(*rsa.PublicKey)
  204. if !ok {
  205. t.Fatalf("not RSA public key")
  206. }
  207. ciphertext, err := rsa.EncryptOAEP(getHash(hash), rand.Reader, rsaPub, []byte(plaintext), nil)
  208. require.NoError(t, err)
  209. return ciphertext
  210. }
  211. func TestFuncMapDoesNotExposeGetHostByName(t *testing.T) {
  212. if _, ok := FuncMap()["getHostByName"]; ok {
  213. t.Fatalf("getHostByName should not be exposed in the template function map")
  214. }
  215. }
  216. func TestExecute(t *testing.T) {
  217. tbl := []struct {
  218. name string
  219. tpl map[string][]byte
  220. labelsTpl map[string][]byte
  221. annotationsTpl map[string][]byte
  222. stringDataTpl map[string][]byte
  223. data map[string][]byte
  224. expectedData map[string][]byte
  225. expectedStringData map[string]string
  226. expectedLabels map[string]string
  227. expectedAnnotations map[string]string
  228. leftDelimiter string
  229. rightDelimiter string
  230. expErr string
  231. expLblErr string
  232. expAnnoErr string
  233. expStrErr string
  234. }{
  235. {
  236. name: "test empty",
  237. tpl: nil,
  238. labelsTpl: nil,
  239. annotationsTpl: nil,
  240. data: nil,
  241. },
  242. {
  243. name: "b64dec func",
  244. tpl: map[string][]byte{
  245. "foo": []byte("{{ .secret | b64dec }}"),
  246. },
  247. data: map[string][]byte{
  248. "secret": []byte("MTIzNA=="),
  249. },
  250. expectedData: map[string][]byte{
  251. "foo": []byte("1234"),
  252. },
  253. },
  254. {
  255. name: "fromJson func",
  256. tpl: map[string][]byte{
  257. "foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo }}"),
  258. },
  259. data: map[string][]byte{
  260. "secret": []byte(`{"foo": "bar"}`),
  261. },
  262. expectedData: map[string][]byte{
  263. "foo": []byte("bar"),
  264. },
  265. },
  266. {
  267. name: "from & toJson func",
  268. tpl: map[string][]byte{
  269. "foo": []byte("{{ $var := .secret | fromJson }}{{ $var.foo | toJson }}"),
  270. },
  271. data: map[string][]byte{
  272. "secret": []byte(`{"foo": {"baz":"bang"}}`),
  273. },
  274. expectedData: map[string][]byte{
  275. "foo": []byte(`{"baz":"bang"}`),
  276. },
  277. },
  278. {
  279. name: "fromJson & toYaml func",
  280. tpl: map[string][]byte{
  281. "foo": []byte("{{ $var := .secret | fromJson | toYaml }}{{ $var }}"),
  282. },
  283. data: map[string][]byte{
  284. "secret": []byte(`{"foo": "bar"}`),
  285. },
  286. expectedData: map[string][]byte{
  287. "foo": []byte(`foo: bar`),
  288. },
  289. },
  290. {
  291. name: "fromYaml & toJson func",
  292. tpl: map[string][]byte{
  293. "foo": []byte("{{ $var := .secret | fromYaml | toJson }}{{ $var }}"),
  294. },
  295. data: map[string][]byte{
  296. "secret": []byte(`foo: bar`),
  297. },
  298. expectedData: map[string][]byte{
  299. "foo": []byte(`{"foo":"bar"}`),
  300. },
  301. },
  302. {
  303. name: "use sprig functions",
  304. tpl: map[string][]byte{
  305. "foo": []byte(`{{ .path | ext }}`),
  306. },
  307. data: map[string][]byte{
  308. "path": []byte(`foo/bar/baz.exe`),
  309. },
  310. expectedData: map[string][]byte{
  311. "foo": []byte(`.exe`),
  312. },
  313. },
  314. {
  315. name: "use replace function",
  316. tpl: map[string][]byte{
  317. "foo": []byte(`{{ .conn | replace "postgres://" "db+postgresql://"}}`),
  318. },
  319. data: map[string][]byte{
  320. "conn": []byte(`postgres://user:pass@db.host:5432/dbname`),
  321. },
  322. expectedData: map[string][]byte{
  323. "foo": []byte(`db+postgresql://user:pass@db.host:5432/dbname`),
  324. },
  325. },
  326. {
  327. name: "use upper function",
  328. tpl: map[string][]byte{
  329. "foo": []byte(`{{ .value | upper }}`),
  330. },
  331. data: map[string][]byte{
  332. "value": []byte(`username`),
  333. },
  334. expectedData: map[string][]byte{
  335. "foo": []byte(`USERNAME`),
  336. },
  337. },
  338. {
  339. name: "multiline template",
  340. tpl: map[string][]byte{
  341. "cfg": []byte(`
  342. datasources:
  343. - name: Graphite
  344. type: graphite
  345. access: proxy
  346. url: http://localhost:8080
  347. password: "{{ .password }}"
  348. user: "{{ .user }}"`),
  349. },
  350. data: map[string][]byte{
  351. "user": []byte(`foobert`),
  352. "password": []byte("harharhar"),
  353. },
  354. expectedData: map[string][]byte{
  355. "cfg": []byte(`
  356. datasources:
  357. - name: Graphite
  358. type: graphite
  359. access: proxy
  360. url: http://localhost:8080
  361. password: "harharhar"
  362. user: "foobert"`),
  363. },
  364. },
  365. {
  366. name: "base64 pipeline",
  367. tpl: map[string][]byte{
  368. "foo": []byte(`{{ "123412341234" | b64enc | b64dec }}`),
  369. },
  370. data: map[string][]byte{},
  371. expectedData: map[string][]byte{
  372. "foo": []byte("123412341234"),
  373. },
  374. },
  375. {
  376. name: "base64 pkcs12 extract",
  377. tpl: map[string][]byte{
  378. "key": []byte(`{{ .secret | b64dec | pkcs12key }}`),
  379. "cert": []byte(`{{ .secret | b64dec | pkcs12cert }}`),
  380. },
  381. data: map[string][]byte{
  382. "secret": []byte(pkcs12ContentNoPass),
  383. },
  384. expectedData: map[string][]byte{
  385. "key": []byte(pkcs12Key),
  386. "cert": []byte(pkcs12Cert),
  387. },
  388. },
  389. {
  390. name: "base64 pkcs12 extract with password",
  391. tpl: map[string][]byte{
  392. "key": []byte(`{{ .secret | b64dec | pkcs12keyPass "123456" }}`),
  393. "cert": []byte(`{{ .secret | b64dec | pkcs12certPass "123456" }}`),
  394. },
  395. data: map[string][]byte{
  396. "secret": []byte(pkcs12ContentWithPass),
  397. },
  398. expectedData: map[string][]byte{
  399. "key": []byte(pkcs12Key),
  400. "cert": []byte(pkcs12Cert),
  401. },
  402. },
  403. {
  404. name: "base64 decode error",
  405. tpl: map[string][]byte{
  406. "key": []byte(`{{ .example | b64dec }}`),
  407. },
  408. data: map[string][]byte{
  409. "example": []byte("iam_no_base64"),
  410. },
  411. expErr: "", // silent error
  412. },
  413. {
  414. name: "pkcs12 key wrong password",
  415. tpl: map[string][]byte{
  416. "key": []byte(`{{ .secret | b64dec | pkcs12keyPass "wrong" }}`),
  417. },
  418. data: map[string][]byte{
  419. "secret": []byte(pkcs12ContentWithPass),
  420. },
  421. expErr: "unable to decode pkcs12",
  422. },
  423. {
  424. name: "pkcs12 cert wrong password",
  425. tpl: map[string][]byte{
  426. "cert": []byte(`{{ .secret | b64dec | pkcs12certPass "wrong" }}`),
  427. },
  428. data: map[string][]byte{
  429. "secret": []byte(pkcs12ContentWithPass),
  430. },
  431. expErr: "unable to decode pkcs12",
  432. },
  433. {
  434. name: "fromJson error",
  435. tpl: map[string][]byte{
  436. "key": []byte(`{{ "{ # no json # }" | fromJson }}`),
  437. },
  438. data: map[string][]byte{},
  439. expErr: "", // silent error
  440. },
  441. {
  442. name: "template syntax error",
  443. tpl: map[string][]byte{
  444. "key": []byte(`{{ #xx }}`),
  445. },
  446. data: map[string][]byte{},
  447. expErr: "unable to parse template",
  448. },
  449. {
  450. name: "unknown key error",
  451. tpl: map[string][]byte{
  452. "key": []byte(`{{ .unknown }}`),
  453. },
  454. data: map[string][]byte{},
  455. expErr: "unable to execute template at key key",
  456. },
  457. {
  458. name: "jwk rsa pub pem",
  459. tpl: map[string][]byte{
  460. "fn": []byte(`{{ .secret | jwkPublicKeyPem }}`),
  461. },
  462. data: map[string][]byte{
  463. "secret": []byte(jwkPubRSA),
  464. },
  465. expectedData: map[string][]byte{
  466. "fn": []byte(jwkPubRSAPKIX),
  467. },
  468. },
  469. {
  470. name: "jwk rsa priv pem",
  471. tpl: map[string][]byte{
  472. "fn": []byte(`{{ .secret | jwkPrivateKeyPem }}`),
  473. },
  474. data: map[string][]byte{
  475. "secret": []byte(jwkPrivRSA),
  476. },
  477. expectedData: map[string][]byte{
  478. "fn": []byte(jwkPrivRSAPKCS8),
  479. },
  480. },
  481. {
  482. name: "jwk ecdsa pub pem",
  483. tpl: map[string][]byte{
  484. "fn": []byte(`{{ .secret | jwkPublicKeyPem }}`),
  485. },
  486. data: map[string][]byte{
  487. "secret": []byte(jwkPubEC),
  488. },
  489. expectedData: map[string][]byte{
  490. "fn": []byte(jwkPubECPKIX),
  491. },
  492. },
  493. {
  494. name: "jwk ecdsa priv pem",
  495. tpl: map[string][]byte{
  496. "fn": []byte(`{{ .secret | jwkPrivateKeyPem }}`),
  497. },
  498. data: map[string][]byte{
  499. "secret": []byte(jwkPrivEC),
  500. },
  501. expectedData: map[string][]byte{
  502. "fn": []byte(jwkPrivECPKCS8),
  503. },
  504. },
  505. {
  506. name: "filter pem certificate",
  507. tpl: map[string][]byte{
  508. "fn": []byte(`{{ .secret | filterPEM "CERTIFICATE" }}`),
  509. },
  510. data: map[string][]byte{
  511. "secret": []byte(jwkPrivRSAPKCS8 + pkcs12Cert),
  512. },
  513. expectedData: map[string][]byte{
  514. "fn": []byte(pkcs12Cert),
  515. },
  516. },
  517. {
  518. name: "labels",
  519. tpl: map[string][]byte{
  520. "foo": []byte("{{ .secret | b64dec }}"),
  521. },
  522. labelsTpl: map[string][]byte{
  523. "bar": []byte("{{ .env | b64dec }}"),
  524. },
  525. data: map[string][]byte{
  526. "secret": []byte("MTIzNA=="),
  527. "env": []byte("ZGV2"),
  528. },
  529. expectedData: map[string][]byte{
  530. "foo": []byte("1234"),
  531. },
  532. expectedLabels: map[string]string{
  533. "bar": "dev",
  534. },
  535. },
  536. {
  537. name: "annotations",
  538. tpl: map[string][]byte{
  539. "foo": []byte("{{ .secret | b64dec }}"),
  540. },
  541. annotationsTpl: map[string][]byte{
  542. "bar": []byte("{{ .env | b64dec }}"),
  543. },
  544. data: map[string][]byte{
  545. "secret": []byte("MTIzNA=="),
  546. "env": []byte("ZGV2"),
  547. },
  548. expectedData: map[string][]byte{
  549. "foo": []byte("1234"),
  550. },
  551. expectedAnnotations: map[string]string{
  552. "bar": "dev",
  553. },
  554. },
  555. {
  556. name: "stringData",
  557. stringDataTpl: map[string][]byte{
  558. "foo": []byte("{{ .secret | b64dec }}"),
  559. },
  560. data: map[string][]byte{
  561. "secret": []byte("MTIzNA=="),
  562. "env": []byte("ZGV2"),
  563. },
  564. expectedStringData: map[string]string{
  565. "foo": "1234",
  566. },
  567. },
  568. {
  569. name: "NonStandardDelimiters",
  570. stringDataTpl: map[string][]byte{
  571. "foo": []byte("<< .secret | b64dec >>"),
  572. },
  573. leftDelimiter: "<<",
  574. rightDelimiter: ">>",
  575. data: map[string][]byte{
  576. "secret": []byte("MTIzNA=="),
  577. "env": []byte("ZGV2"),
  578. },
  579. expectedStringData: map[string]string{
  580. "foo": "1234",
  581. },
  582. },
  583. {
  584. name: "rsa decrypt rsa-oaep sha1 pkcs8 data base64",
  585. tpl: map[string][]byte{
  586. "data_decrypted": []byte(`{{ .private_key | rsaDecrypt "RSA-OAEP" "SHA1" (.data_crypted_base64 | b64dec) }}`),
  587. },
  588. data: map[string][]byte{
  589. "private_key": []byte(rsaDecryptPKRSAPKCS8),
  590. "data_crypted_base64": []byte(rsaDecryptDataPKCS8Base64),
  591. },
  592. expectedData: map[string][]byte{
  593. "data_decrypted": []byte("a1b2c3d4"),
  594. },
  595. },
  596. {
  597. name: "rsa decrypt rsa-oaep sha256 pkcs1 data base64",
  598. tpl: map[string][]byte{
  599. "data_decrypted": []byte(`{{ .private_key | rsaDecrypt "RSA-OAEP" "SHA256" (.data_crypted_base64 | b64dec) }}`),
  600. },
  601. data: map[string][]byte{
  602. "private_key": []byte(rsaDecryptPKRSAPKCS1),
  603. "data_crypted_base64": []byte(rsaDecryptDataPKCS1Base64),
  604. },
  605. expectedData: map[string][]byte{
  606. "data_decrypted": []byte("hellopkcs1sha256"),
  607. },
  608. },
  609. {
  610. name: "rsa decrypt rsa-oaep sha256 pkcs1 data bin",
  611. tpl: map[string][]byte{
  612. "data_decrypted": []byte(`{{ .private_key | rsaDecrypt "RSA-OAEP" "SHA256" .data_crypted_bin }}`),
  613. },
  614. data: map[string][]byte{
  615. "private_key": []byte(rsaDecryptPKRSAPKCS1),
  616. "data_crypted_bin": rsaEncryptOAEP(t, []byte(rsaDecryptPubKeyRSAPKCS1), "SHA256", "hellopkcs1sha256"),
  617. },
  618. expectedData: map[string][]byte{
  619. "data_decrypted": []byte("hellopkcs1sha256"),
  620. },
  621. },
  622. {
  623. name: "certSANs extract DNS SANs as comma-separated string",
  624. tpl: map[string][]byte{
  625. "sans": []byte(`{{ .certificate | certSANs | join "," }}`),
  626. },
  627. data: map[string][]byte{
  628. "certificate": []byte(pkcs12Cert),
  629. },
  630. expectedData: map[string][]byte{
  631. "sans": []byte("gooble.com"),
  632. },
  633. },
  634. {
  635. name: "certSANs extract first SAN with index",
  636. tpl: map[string][]byte{
  637. "primary-domain": []byte(`{{ index (.certificate | certSANs) 0 }}`),
  638. },
  639. data: map[string][]byte{
  640. "certificate": []byte(pkcs12Cert),
  641. },
  642. expectedData: map[string][]byte{
  643. "primary-domain": []byte("gooble.com"),
  644. },
  645. },
  646. {
  647. name: "certSANs with toJson",
  648. tpl: map[string][]byte{
  649. "sans-json": []byte(`{{ .certificate | certSANs | toJson }}`),
  650. },
  651. data: map[string][]byte{
  652. "certificate": []byte(pkcs12Cert),
  653. },
  654. expectedData: map[string][]byte{
  655. "sans-json": []byte(`["gooble.com"]`),
  656. },
  657. },
  658. {
  659. name: "certSANs combined with filterPEM pipeline",
  660. tpl: map[string][]byte{
  661. "sans": []byte(`{{ .secret | filterPEM "CERTIFICATE" | certSANs | join "," }}`),
  662. },
  663. data: map[string][]byte{
  664. "secret": []byte(pkcs12Key + pkcs12Cert),
  665. },
  666. expectedData: map[string][]byte{
  667. "sans": []byte("gooble.com"),
  668. },
  669. },
  670. {
  671. name: "certSANs with invalid PEM",
  672. tpl: map[string][]byte{
  673. "sans": []byte(`{{ .certificate | certSANs }}`),
  674. },
  675. data: map[string][]byte{
  676. "certificate": []byte("not-a-pem"),
  677. },
  678. expErr: "failed to decode PEM block",
  679. },
  680. {
  681. name: "htpasswd with sha1",
  682. tpl: map[string][]byte{
  683. ".htpasswd": []byte(`{{ htpasswd .username .password "sha" }}`),
  684. },
  685. data: map[string][]byte{
  686. "username": []byte("foo1"),
  687. "password": []byte("FZ4jR;l]ON;pHKi=_'zh79P"),
  688. },
  689. expectedData: map[string][]byte{
  690. ".htpasswd": []byte("foo1:{SHA}wtdJD6OIjUniEJkTlewnKzfFxA4="),
  691. },
  692. },
  693. }
  694. for _, tt := range tbl {
  695. t.Run(tt.name, func(t *testing.T) {
  696. sec := &corev1.Secret{
  697. Data: make(map[string][]byte),
  698. StringData: make(map[string]string),
  699. ObjectMeta: v1.ObjectMeta{Labels: make(map[string]string), Annotations: make(map[string]string)},
  700. }
  701. oldLeftDelim := leftDelim
  702. oldRightDelim := rightDelim
  703. if tt.leftDelimiter != "" {
  704. leftDelim = tt.leftDelimiter
  705. }
  706. if tt.rightDelimiter != "" {
  707. rightDelim = tt.rightDelimiter
  708. }
  709. defer func() {
  710. leftDelim = oldLeftDelim
  711. rightDelim = oldRightDelim
  712. }()
  713. err := Execute(tt.tpl, tt.data, esapi.TemplateScopeValues, esapi.TemplateTargetData, sec)
  714. if !ErrorContains(err, tt.expErr) {
  715. t.Errorf("unexpected error: %s, expected: %s", err, tt.expErr)
  716. }
  717. err = Execute(tt.labelsTpl, tt.data, esapi.TemplateScopeValues, esapi.TemplateTargetLabels, sec)
  718. if !ErrorContains(err, tt.expLblErr) {
  719. t.Errorf("unexpected error: %s, expected: %s", err, tt.expErr)
  720. }
  721. err = Execute(tt.annotationsTpl, tt.data, esapi.TemplateScopeValues, esapi.TemplateTargetAnnotations, sec)
  722. if !ErrorContains(err, tt.expAnnoErr) {
  723. t.Errorf("unexpected error: %s, expected: %s", err, tt.expErr)
  724. }
  725. if tt.expectedData != nil {
  726. assert.EqualValues(t, tt.expectedData, sec.Data)
  727. }
  728. if tt.expectedLabels != nil {
  729. assert.EqualValues(t, tt.expectedLabels, sec.ObjectMeta.Labels)
  730. }
  731. if tt.expectedAnnotations != nil {
  732. assert.EqualValues(t, tt.expectedAnnotations, sec.ObjectMeta.Annotations)
  733. }
  734. })
  735. }
  736. }
  737. func TestScopeValuesWithSecretFieldsNil(t *testing.T) {
  738. tbl := []struct {
  739. name string
  740. tpl map[string][]byte
  741. target string
  742. data map[string][]byte
  743. expectedData map[string][]byte
  744. expectedStringData map[string]string
  745. expErr string
  746. }{
  747. {
  748. name: "test empty",
  749. tpl: map[string][]byte{},
  750. target: esapi.TemplateTargetData,
  751. data: nil,
  752. },
  753. {
  754. name: "test byte",
  755. tpl: map[string][]byte{"foo": []byte("bar")},
  756. target: esapi.TemplateTargetData,
  757. data: map[string][]byte{
  758. "key": []byte("foo"),
  759. "value": []byte("bar"),
  760. },
  761. expectedData: map[string][]byte{
  762. "foo": []byte("bar"),
  763. },
  764. },
  765. {
  766. name: "test Annotations",
  767. tpl: map[string][]byte{"foo": []byte("bar")},
  768. target: esapi.TemplateTargetAnnotations,
  769. data: map[string][]byte{
  770. "key": []byte("foo"),
  771. "value": []byte("bar"),
  772. },
  773. expectedStringData: map[string]string{
  774. "foo": "bar",
  775. },
  776. },
  777. {
  778. name: "test Labels",
  779. tpl: map[string][]byte{"foo": []byte("bar")},
  780. target: esapi.TemplateTargetLabels,
  781. data: map[string][]byte{
  782. "key": []byte("foo"),
  783. "value": []byte("bar"),
  784. },
  785. expectedStringData: map[string]string{
  786. "foo": "bar",
  787. },
  788. },
  789. }
  790. for i := range tbl {
  791. row := tbl[i]
  792. t.Run(row.name, func(t *testing.T) {
  793. sec := &corev1.Secret{}
  794. err := Execute(row.tpl, row.data, esapi.TemplateScopeValues, row.target, sec)
  795. if !ErrorContains(err, row.expErr) {
  796. t.Errorf("unexpected error: %s, expected: %s", err, row.expErr)
  797. }
  798. switch row.target {
  799. case esapi.TemplateTargetData:
  800. if row.expectedData != nil {
  801. assert.EqualValues(t, row.expectedData, sec.Data)
  802. }
  803. case esapi.TemplateTargetLabels:
  804. if row.expectedStringData != nil {
  805. assert.EqualValues(t, row.expectedStringData, sec.Labels)
  806. }
  807. case esapi.TemplateTargetAnnotations:
  808. if row.expectedStringData != nil {
  809. assert.EqualValues(t, row.expectedStringData, sec.Annotations)
  810. }
  811. }
  812. })
  813. }
  814. }
  815. func TestExecuteInvalidTemplateScope(t *testing.T) {
  816. sec := &corev1.Secret{}
  817. err := Execute(map[string][]byte{"foo": []byte("bar")}, nil, "invalid", esapi.TemplateTargetData, sec)
  818. require.Error(t, err)
  819. assert.ErrorContains(t, err, "expected 'Values' or 'KeysAndValues'")
  820. }
  821. func TestScopeKeysAndValues(t *testing.T) {
  822. tbl := []struct {
  823. name string
  824. tpl map[string][]byte
  825. target string
  826. data map[string][]byte
  827. expectedData map[string][]byte
  828. expectedStringData map[string]string
  829. expErr string
  830. }{
  831. {
  832. name: "test empty",
  833. tpl: map[string][]byte{"literal": []byte("")},
  834. target: "Data",
  835. data: nil,
  836. },
  837. {
  838. name: "test base64",
  839. tpl: map[string][]byte{"literal": []byte("{{ .key }}: {{ .value }}")},
  840. target: esapi.TemplateTargetData,
  841. data: map[string][]byte{
  842. "key": []byte("foo"),
  843. "value": []byte("bar"),
  844. },
  845. expectedData: map[string][]byte{
  846. "foo": []byte("bar"),
  847. },
  848. },
  849. {
  850. name: "test Annotations",
  851. tpl: map[string][]byte{"literal": []byte("{{ .key }}: {{ .value }}")},
  852. target: esapi.TemplateTargetAnnotations,
  853. data: map[string][]byte{
  854. "key": []byte("foo"),
  855. "value": []byte("bar"),
  856. },
  857. expectedStringData: map[string]string{
  858. "foo": "bar",
  859. },
  860. },
  861. {
  862. name: "test Labels",
  863. tpl: map[string][]byte{"literal": []byte("{{ .key }}: {{ .value }}")},
  864. target: esapi.TemplateTargetLabels,
  865. data: map[string][]byte{
  866. "key": []byte("foo"),
  867. "value": []byte("bar"),
  868. },
  869. expectedStringData: map[string]string{
  870. "foo": "bar",
  871. },
  872. },
  873. }
  874. for i := range tbl {
  875. row := tbl[i]
  876. t.Run(row.name, func(t *testing.T) {
  877. sec := &corev1.Secret{
  878. Data: make(map[string][]byte),
  879. StringData: make(map[string]string),
  880. ObjectMeta: v1.ObjectMeta{Labels: make(map[string]string), Annotations: make(map[string]string)},
  881. }
  882. err := Execute(row.tpl, row.data, esapi.TemplateScopeKeysAndValues, row.target, sec)
  883. if !ErrorContains(err, row.expErr) {
  884. t.Errorf("unexpected error: %s, expected: %s", err, row.expErr)
  885. }
  886. switch row.target {
  887. case esapi.TemplateTargetData:
  888. if row.expectedData != nil {
  889. assert.EqualValues(t, row.expectedData, sec.Data)
  890. }
  891. case esapi.TemplateTargetLabels:
  892. if row.expectedStringData != nil {
  893. assert.EqualValues(t, row.expectedStringData, sec.Labels)
  894. }
  895. case esapi.TemplateTargetAnnotations:
  896. if row.expectedStringData != nil {
  897. assert.EqualValues(t, row.expectedStringData, sec.Annotations)
  898. }
  899. }
  900. })
  901. }
  902. }
  903. func TestComplexYAMLFieldsWithSpec(t *testing.T) {
  904. // These tests verify that the template engine can handle complex YAML values
  905. // for spec fields. Since ConfigMap doesn't have a spec field in its typed definition,
  906. // we test by inspecting what would be set in an unstructured representation.
  907. type testCase struct {
  908. name string
  909. tpl map[string][]byte
  910. target string
  911. scope esapi.TemplateScope
  912. data map[string][]byte
  913. verify func(t *testing.T, obj *corev1.Secret)
  914. expErr string
  915. }
  916. tests := []testCase{
  917. {
  918. name: "data target with simple string in Secret",
  919. target: "data",
  920. scope: esapi.TemplateScopeValues,
  921. tpl: map[string][]byte{
  922. "simple": []byte("{{ .value }}"),
  923. },
  924. data: map[string][]byte{
  925. "value": []byte("test-value"),
  926. },
  927. verify: func(t *testing.T, obj *corev1.Secret) {
  928. assert.Equal(t, []byte("test-value"), obj.Data["simple"])
  929. },
  930. },
  931. {
  932. name: "data target with multiple keys",
  933. target: "data",
  934. scope: esapi.TemplateScopeValues,
  935. tpl: map[string][]byte{
  936. "username": []byte("{{ .user }}"),
  937. "password": []byte("{{ .pass }}"),
  938. },
  939. data: map[string][]byte{
  940. "user": []byte("admin"),
  941. "pass": []byte("secret123"),
  942. },
  943. verify: func(t *testing.T, obj *corev1.Secret) {
  944. assert.Equal(t, []byte("admin"), obj.Data["username"])
  945. assert.Equal(t, []byte("secret123"), obj.Data["password"])
  946. },
  947. },
  948. {
  949. name: "labels target with templated values",
  950. target: "labels",
  951. scope: esapi.TemplateScopeValues,
  952. tpl: map[string][]byte{
  953. "app": []byte("{{ .app }}"),
  954. "version": []byte("{{ .version }}"),
  955. },
  956. data: map[string][]byte{
  957. "app": []byte("my-app"),
  958. "version": []byte("1.0.0"),
  959. },
  960. verify: func(t *testing.T, obj *corev1.Secret) {
  961. assert.Equal(t, "my-app", obj.Labels["app"])
  962. assert.Equal(t, "1.0.0", obj.Labels["version"])
  963. },
  964. },
  965. {
  966. name: "annotations target with templated values",
  967. target: "annotations",
  968. scope: esapi.TemplateScopeValues,
  969. tpl: map[string][]byte{
  970. "description": []byte("{{ .desc }}"),
  971. "owner": []byte("{{ .owner }}"),
  972. },
  973. data: map[string][]byte{
  974. "desc": []byte("Test secret"),
  975. "owner": []byte("team-platform"),
  976. },
  977. verify: func(t *testing.T, obj *corev1.Secret) {
  978. assert.Equal(t, "Test secret", obj.Annotations["description"])
  979. assert.Equal(t, "team-platform", obj.Annotations["owner"])
  980. },
  981. },
  982. }
  983. for _, tt := range tests {
  984. t.Run(tt.name, func(t *testing.T) {
  985. obj := &corev1.Secret{
  986. ObjectMeta: v1.ObjectMeta{
  987. Name: "test-secret",
  988. Namespace: "default",
  989. Labels: make(map[string]string),
  990. Annotations: make(map[string]string),
  991. },
  992. Data: make(map[string][]byte),
  993. }
  994. err := Execute(tt.tpl, tt.data, tt.scope, tt.target, obj)
  995. if tt.expErr != "" {
  996. require.Error(t, err)
  997. assert.Contains(t, err.Error(), tt.expErr)
  998. return
  999. }
  1000. require.NoError(t, err)
  1001. if tt.verify != nil {
  1002. tt.verify(t, obj)
  1003. }
  1004. })
  1005. }
  1006. }
  1007. func TestTryParseYAML(t *testing.T) {
  1008. tests := []struct {
  1009. name string
  1010. input any
  1011. expected any
  1012. }{
  1013. {
  1014. name: "parse YAML object",
  1015. input: "key: value\nfoo: bar",
  1016. expected: map[string]any{"key": "value", "foo": "bar"},
  1017. },
  1018. {
  1019. name: "parse YAML array",
  1020. input: "- item1\n- item2\n- item3",
  1021. expected: []any{"item1", "item2", "item3"},
  1022. },
  1023. {
  1024. name: "parse YAML number",
  1025. input: "42",
  1026. expected: int64(42),
  1027. },
  1028. {
  1029. name: "parse YAML boolean true",
  1030. input: "true",
  1031. expected: true,
  1032. },
  1033. {
  1034. name: "parse YAML boolean false",
  1035. input: "false",
  1036. expected: false,
  1037. },
  1038. {
  1039. name: "parse YAML float",
  1040. input: "3.14",
  1041. expected: 3.14,
  1042. },
  1043. {
  1044. name: "parse complex YAML",
  1045. input: "database:\n host: localhost\n port: 5432\n enabled: true",
  1046. expected: map[string]any{"database": map[string]any{"host": "localhost", "port": int64(5432), "enabled": true}},
  1047. },
  1048. {
  1049. name: "plain string returns as-is",
  1050. input: "just a string",
  1051. expected: "just a string",
  1052. },
  1053. {
  1054. name: "invalid YAML returns original",
  1055. input: "invalid: : yaml:",
  1056. expected: "invalid: : yaml:",
  1057. },
  1058. {
  1059. name: "non-string input returns as-is",
  1060. input: 123,
  1061. expected: 123,
  1062. },
  1063. {
  1064. name: "byte slice returns as-is",
  1065. input: []byte("test"),
  1066. expected: []byte("test"),
  1067. },
  1068. {
  1069. name: "null/empty string",
  1070. input: "",
  1071. expected: nil,
  1072. },
  1073. }
  1074. for _, tt := range tests {
  1075. t.Run(tt.name, func(t *testing.T) {
  1076. result := tryParseYAML(tt.input)
  1077. assert.Equal(t, tt.expected, result)
  1078. })
  1079. }
  1080. }
  1081. func ErrorContains(out error, want string) bool {
  1082. if out == nil {
  1083. return want == ""
  1084. }
  1085. if want == "" {
  1086. return false
  1087. }
  1088. return strings.Contains(out.Error(), want)
  1089. }
  1090. func TestPkcs12certPass(t *testing.T) {
  1091. const (
  1092. leafCertPath = "_testdata/foo.crt"
  1093. intermediateCertPath = "_testdata/intermediate-ca.crt"
  1094. rootCertPath = "_testdata/root-ca.crt"
  1095. disjunctCertPath = "_testdata/disjunct-root-ca.crt"
  1096. )
  1097. type args struct {
  1098. pass string
  1099. filename string
  1100. }
  1101. type testCase struct {
  1102. name string
  1103. args args
  1104. want []string
  1105. wantErr bool
  1106. }
  1107. tests := []testCase{
  1108. {
  1109. // this case expects the whole chain to be stored
  1110. // in a single bag.
  1111. // bag(1): leaf/root/intermediate cert
  1112. // bag(2): private key
  1113. name: "read file without password",
  1114. args: args{
  1115. pass: "",
  1116. filename: "_testdata/foo-nopass.pfx",
  1117. },
  1118. want: []string{
  1119. // this order is important
  1120. leafCertPath,
  1121. intermediateCertPath,
  1122. rootCertPath,
  1123. },
  1124. },
  1125. {
  1126. // same as above but with password
  1127. name: "read file with password",
  1128. args: args{
  1129. pass: "1234",
  1130. filename: "_testdata/foo-withpass-1234.pfx",
  1131. },
  1132. want: []string{
  1133. // this order is important
  1134. leafCertPath,
  1135. intermediateCertPath,
  1136. rootCertPath,
  1137. },
  1138. },
  1139. {
  1140. // cert chain may be stored in different bags
  1141. // this test case uses a pfx that has the following structure:
  1142. // bag(1): leaf certificate
  1143. // bag(2): root + intermediate cert
  1144. // bag(3): private key
  1145. name: "read multibag cert chain",
  1146. args: args{
  1147. pass: "",
  1148. filename: "_testdata/foo-multibag-nopass.pfx",
  1149. },
  1150. want: []string{
  1151. // this order is important
  1152. leafCertPath,
  1153. intermediateCertPath,
  1154. rootCertPath,
  1155. },
  1156. },
  1157. {
  1158. // cert chain may contain a disjunct cert
  1159. // bag(1): leaf/root/intermediate/disjunct
  1160. // bag(2): private key
  1161. name: "read disjunct cert chain",
  1162. args: args{
  1163. pass: "",
  1164. filename: "_testdata/foo-disjunct-nopass.pfx",
  1165. },
  1166. want: []string{
  1167. // this order is important
  1168. leafCertPath,
  1169. rootCertPath,
  1170. intermediateCertPath,
  1171. disjunctCertPath,
  1172. },
  1173. },
  1174. {
  1175. name: "read file wrong password",
  1176. args: args{
  1177. pass: "wrongpass",
  1178. filename: "_testdata/foo-withpass-1234.pfx",
  1179. },
  1180. wantErr: true,
  1181. },
  1182. }
  1183. testFunc := func(t *testing.T, tc testCase) {
  1184. archive, err := os.ReadFile(tc.args.filename)
  1185. if err != nil {
  1186. t.Error(err)
  1187. }
  1188. var expOut []byte
  1189. for _, w := range tc.want {
  1190. c, err := os.ReadFile(w)
  1191. if err != nil {
  1192. t.Error(err)
  1193. }
  1194. expOut = append(expOut, c...)
  1195. }
  1196. got, err := pkcs12certPass(tc.args.pass, string(archive))
  1197. if (err != nil) != tc.wantErr {
  1198. t.Errorf("pkcs12certPass() error = %v, wantErr %v", err, tc.wantErr)
  1199. return
  1200. }
  1201. if diff := cmp.Diff(string(expOut), got); diff != "" {
  1202. t.Errorf("pkcs12certPass() = diff:\n%s", diff)
  1203. }
  1204. }
  1205. for _, tt := range tests {
  1206. t.Run(tt.name, func(t *testing.T) {
  1207. testFunc(t, tt)
  1208. })
  1209. }
  1210. }
  1211. func TestConfigMapDataNotBase64Encoded(t *testing.T) {
  1212. configMap := &corev1.ConfigMap{
  1213. ObjectMeta: v1.ObjectMeta{
  1214. Name: "test-cm",
  1215. Namespace: "default",
  1216. },
  1217. }
  1218. data := map[string][]byte{
  1219. "host": []byte("localhost"),
  1220. "port": []byte("5432"),
  1221. "database": []byte("mydb"),
  1222. }
  1223. tplMap := map[string][]byte{
  1224. "host": []byte("{{ .host }}"),
  1225. "port": []byte("{{ .port }}"),
  1226. "database": []byte("{{ .database }}"),
  1227. }
  1228. err := Execute(tplMap, data, esapi.TemplateScopeValues, "Data", configMap)
  1229. require.NoError(t, err)
  1230. assert.Equal(t, "localhost", configMap.Data["host"], "host should be plain text, not base64")
  1231. assert.Equal(t, "5432", configMap.Data["port"], "port should be plain text, not base64")
  1232. assert.Equal(t, "mydb", configMap.Data["database"], "database should be plain text, not base64")
  1233. }
  1234. func TestNestedPathTargeting(t *testing.T) {
  1235. tests := []struct {
  1236. name string
  1237. target string
  1238. scope esapi.TemplateScope
  1239. tpl map[string][]byte
  1240. data map[string][]byte
  1241. verify func(t *testing.T, obj map[string]any)
  1242. wantErr bool
  1243. errorMsg string
  1244. }{
  1245. {
  1246. name: "nested path spec.slack with template variables",
  1247. target: "spec.slack",
  1248. scope: esapi.TemplateScopeKeysAndValues,
  1249. tpl: map[string][]byte{
  1250. "slack-config": []byte(`
  1251. api_url: {{ .url }}
  1252. webhook_url: {{ .webhook }}
  1253. `),
  1254. },
  1255. data: map[string][]byte{
  1256. "url": []byte("https://hooks.slack.com/services/XXX"),
  1257. "webhook": []byte("https://hooks.slack.com/services/YYY"),
  1258. },
  1259. verify: func(t *testing.T, obj map[string]any) {
  1260. specMap := obj["spec"].(map[string]any)
  1261. slackMap := specMap["slack"].(map[string]any)
  1262. // Should NOT have spec.slack.api_url.url (the bug with template variables)
  1263. apiURL := slackMap["api_url"]
  1264. assert.Equal(t, "https://hooks.slack.com/services/XXX", apiURL, "api_url should be string, not nested map")
  1265. webhookURL := slackMap["webhook_url"]
  1266. assert.Equal(t, "https://hooks.slack.com/services/YYY", webhookURL, "webhook_url should be string, not nested map")
  1267. // Verify the fix: should NOT have duplicate 'slack' in the path
  1268. _, hasDuplicateSlack := slackMap["slack"]
  1269. assert.False(t, hasDuplicateSlack, "should not have spec.slack.slack (the bug)")
  1270. },
  1271. },
  1272. {
  1273. name: "nested path merge behavior - preserves existing fields",
  1274. target: "spec.slack",
  1275. scope: esapi.TemplateScopeKeysAndValues,
  1276. tpl: map[string][]byte{
  1277. "slack-config": []byte(`
  1278. api_url: {{ .url }}
  1279. `),
  1280. },
  1281. data: map[string][]byte{
  1282. "url": []byte("https://hooks.slack.com/services/NEW"),
  1283. },
  1284. verify: func(t *testing.T, obj map[string]any) {
  1285. specMap := obj["spec"].(map[string]any)
  1286. slackMap := specMap["slack"].(map[string]any)
  1287. // Should have the new field from template
  1288. assert.Equal(t, "https://hooks.slack.com/services/NEW", slackMap["api_url"], "api_url should be set from template")
  1289. // Should PRESERVE existing fields that were not in the template
  1290. assert.Equal(t, "general", slackMap["channel"], "existing channel field should be preserved")
  1291. assert.Equal(t, "test-value", slackMap["other_field"], "existing other_field should be preserved")
  1292. },
  1293. },
  1294. {
  1295. name: "nested path overwrite field - updates existing value",
  1296. target: "spec.slack",
  1297. scope: esapi.TemplateScopeKeysAndValues,
  1298. tpl: map[string][]byte{
  1299. "slack-config": []byte(`
  1300. channel: {{ .new_channel }}
  1301. `),
  1302. },
  1303. data: map[string][]byte{
  1304. "new_channel": []byte("alerts"),
  1305. },
  1306. verify: func(t *testing.T, obj map[string]any) {
  1307. specMap := obj["spec"].(map[string]any)
  1308. slackMap := specMap["slack"].(map[string]any)
  1309. // Should update the existing field
  1310. assert.Equal(t, "alerts", slackMap["channel"], "channel should be updated")
  1311. // Should still preserve other existing fields
  1312. assert.Equal(t, "https://hooks.slack.com/existing", slackMap["api_url"], "existing api_url should be preserved")
  1313. assert.Equal(t, "test-value", slackMap["other_field"], "existing other_field should be preserved")
  1314. },
  1315. },
  1316. }
  1317. for _, tt := range tests {
  1318. t.Run(tt.name, func(t *testing.T) {
  1319. // Use an unstructured object to test generic target behavior
  1320. obj := &unstructured.Unstructured{
  1321. Object: map[string]any{
  1322. "apiVersion": "example.com/v1",
  1323. "kind": "TestResource",
  1324. "metadata": map[string]any{
  1325. "name": "test-resource",
  1326. "namespace": "default",
  1327. },
  1328. },
  1329. }
  1330. // For merge behavior tests, pre-populate the object with existing content
  1331. if strings.Contains(tt.name, "merge behavior") {
  1332. obj.Object["spec"] = map[string]any{
  1333. "slack": map[string]any{
  1334. "channel": "general",
  1335. "other_field": "test-value",
  1336. },
  1337. }
  1338. }
  1339. // For overwrite field test, pre-populate with different initial values
  1340. if strings.Contains(tt.name, "overwrite field") {
  1341. obj.Object["spec"] = map[string]any{
  1342. "slack": map[string]any{
  1343. "channel": "general",
  1344. "api_url": "https://hooks.slack.com/existing",
  1345. "other_field": "test-value",
  1346. },
  1347. }
  1348. }
  1349. err := Execute(tt.tpl, tt.data, tt.scope, tt.target, obj)
  1350. if tt.wantErr {
  1351. require.Error(t, err)
  1352. if tt.errorMsg != "" {
  1353. assert.Contains(t, err.Error(), tt.errorMsg)
  1354. }
  1355. } else {
  1356. require.NoError(t, err)
  1357. if tt.verify != nil {
  1358. tt.verify(t, obj.Object)
  1359. }
  1360. }
  1361. })
  1362. }
  1363. }