template.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. "bytes"
  15. "crypto/x509"
  16. "encoding/pem"
  17. "fmt"
  18. tpl "text/template"
  19. "github.com/Masterminds/sprig/v3"
  20. "github.com/lestrrat-go/jwx/jwk"
  21. "golang.org/x/crypto/pkcs12"
  22. corev1 "k8s.io/api/core/v1"
  23. )
  24. var tplFuncs = tpl.FuncMap{
  25. "pkcs12key": pkcs12key,
  26. "pkcs12keyPass": pkcs12keyPass,
  27. "pkcs12cert": pkcs12cert,
  28. "pkcs12certPass": pkcs12certPass,
  29. "jwkPublicKeyPem": jwkPublicKeyPem,
  30. "jwkPrivateKeyPem": jwkPrivateKeyPem,
  31. }
  32. // So other templating calls can use the same extra functions.
  33. func FuncMap() tpl.FuncMap {
  34. return tplFuncs
  35. }
  36. const (
  37. errParse = "unable to parse template at key %s: %s"
  38. errExecute = "unable to execute template at key %s: %s"
  39. errDecodePKCS12WithPass = "unable to decode pkcs12 with password: %s"
  40. errDecodeCertWithPass = "unable to decode pkcs12 certificate with password: %s"
  41. errParsePrivKey = "unable to parse private key type"
  42. pemTypeCertificate = "CERTIFICATE"
  43. )
  44. func init() {
  45. sprigFuncs := sprig.TxtFuncMap()
  46. delete(sprigFuncs, "env")
  47. delete(sprigFuncs, "expandenv")
  48. for k, v := range sprigFuncs {
  49. tplFuncs[k] = v
  50. }
  51. }
  52. // Execute renders the secret data as template. If an error occurs processing is stopped immediately.
  53. func Execute(tpl, data map[string][]byte, secret *corev1.Secret) error {
  54. if tpl == nil {
  55. return nil
  56. }
  57. for k, v := range tpl {
  58. val, err := execute(k, string(v), data)
  59. if err != nil {
  60. return fmt.Errorf(errExecute, k, err)
  61. }
  62. secret.Data[k] = val
  63. }
  64. return nil
  65. }
  66. func execute(k, val string, data map[string][]byte) ([]byte, error) {
  67. strValData := make(map[string]string, len(data))
  68. for k := range data {
  69. strValData[k] = string(data[k])
  70. }
  71. t, err := tpl.New(k).
  72. Funcs(tplFuncs).
  73. Parse(val)
  74. if err != nil {
  75. return nil, fmt.Errorf(errParse, k, err)
  76. }
  77. buf := bytes.NewBuffer(nil)
  78. err = t.Execute(buf, strValData)
  79. if err != nil {
  80. return nil, fmt.Errorf(errExecute, k, err)
  81. }
  82. return buf.Bytes(), nil
  83. }
  84. func pkcs12keyPass(pass, input string) (string, error) {
  85. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  86. if err != nil {
  87. return "", fmt.Errorf(errDecodePKCS12WithPass, err)
  88. }
  89. var pemData []byte
  90. for _, block := range blocks {
  91. // remove bag attributes like localKeyID, friendlyName
  92. block.Headers = nil
  93. if block.Type == pemTypeCertificate {
  94. continue
  95. }
  96. key, err := parsePrivateKey(block.Bytes)
  97. if err != nil {
  98. return "", err
  99. }
  100. // we use pkcs8 because it supports more key types (ecdsa, ed25519), not just RSA
  101. block.Bytes, err = x509.MarshalPKCS8PrivateKey(key)
  102. if err != nil {
  103. return "", err
  104. }
  105. // report error if encode fails
  106. var buf bytes.Buffer
  107. if err := pem.Encode(&buf, block); err != nil {
  108. return "", err
  109. }
  110. pemData = append(pemData, buf.Bytes()...)
  111. }
  112. return string(pemData), nil
  113. }
  114. func parsePrivateKey(block []byte) (interface{}, error) {
  115. if k, err := x509.ParsePKCS1PrivateKey(block); err == nil {
  116. return k, nil
  117. }
  118. if k, err := x509.ParsePKCS8PrivateKey(block); err == nil {
  119. return k, nil
  120. }
  121. if k, err := x509.ParseECPrivateKey(block); err == nil {
  122. return k, nil
  123. }
  124. return nil, fmt.Errorf(errParsePrivKey)
  125. }
  126. func pkcs12key(input string) (string, error) {
  127. return pkcs12keyPass("", input)
  128. }
  129. func pkcs12certPass(pass, input string) (string, error) {
  130. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  131. if err != nil {
  132. return "", fmt.Errorf(errDecodeCertWithPass, err)
  133. }
  134. var pemData []byte
  135. for _, block := range blocks {
  136. if block.Type != pemTypeCertificate {
  137. continue
  138. }
  139. // remove bag attributes like localKeyID, friendlyName
  140. block.Headers = nil
  141. // report error if encode fails
  142. var buf bytes.Buffer
  143. if err := pem.Encode(&buf, block); err != nil {
  144. return "", err
  145. }
  146. pemData = append(pemData, buf.Bytes()...)
  147. }
  148. // try to order certificate chain. If it fails we return
  149. // the unordered raw pem data.
  150. // This fails if multiple leaf or disjunct certs are provided.
  151. ordered, err := fetchCertChains(pemData)
  152. if err != nil {
  153. return string(pemData), nil
  154. }
  155. return string(ordered), nil
  156. }
  157. func pkcs12cert(input string) (string, error) {
  158. return pkcs12certPass("", input)
  159. }
  160. func jwkPublicKeyPem(jwkjson string) (string, error) {
  161. k, err := jwk.ParseKey([]byte(jwkjson))
  162. if err != nil {
  163. return "", err
  164. }
  165. var rawkey interface{}
  166. err = k.Raw(&rawkey)
  167. if err != nil {
  168. return "", err
  169. }
  170. mpk, err := x509.MarshalPKIXPublicKey(rawkey)
  171. if err != nil {
  172. return "", err
  173. }
  174. return pemEncode(string(mpk), "PUBLIC KEY")
  175. }
  176. func jwkPrivateKeyPem(jwkjson string) (string, error) {
  177. k, err := jwk.ParseKey([]byte(jwkjson))
  178. if err != nil {
  179. return "", err
  180. }
  181. var mpk []byte
  182. var pk interface{}
  183. err = k.Raw(&pk)
  184. if err != nil {
  185. return "", err
  186. }
  187. mpk, err = x509.MarshalPKCS8PrivateKey(pk)
  188. if err != nil {
  189. return "", err
  190. }
  191. return pemEncode(string(mpk), "PRIVATE KEY")
  192. }
  193. func pemEncode(thing, kind string) (string, error) {
  194. buf := bytes.NewBuffer(nil)
  195. err := pem.Encode(buf, &pem.Block{Type: kind, Bytes: []byte(thing)})
  196. return buf.String(), err
  197. }