template.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. "encoding/base64"
  16. "encoding/json"
  17. "encoding/pem"
  18. "strings"
  19. tpl "text/template"
  20. "github.com/youmark/pkcs8"
  21. "golang.org/x/crypto/pkcs12"
  22. corev1 "k8s.io/api/core/v1"
  23. ctrl "sigs.k8s.io/controller-runtime"
  24. )
  25. var tplFuncs = tpl.FuncMap{
  26. "pkcs12key": pkcs12key,
  27. "pkcs12keyPass": pkcs12keyPass,
  28. "pkcs12cert": pkcs12cert,
  29. "pkcs12certPass": pkcs12certPass,
  30. "pemPrivateKey": pemPrivateKey,
  31. "pemCertificate": pemCertificate,
  32. "base64decode": base64decode,
  33. "base64encode": base64encode,
  34. "fromJSON": fromJSON,
  35. "toJSON": toJSON,
  36. "toString": toString,
  37. "toBytes": toBytes,
  38. "upper": strings.ToUpper,
  39. "lower": strings.ToLower,
  40. }
  41. var log = ctrl.Log.WithName("template")
  42. // Execute uses an best-effort approach to render the secret data as template.
  43. func Execute(secret *corev1.Secret, data map[string][]byte) error {
  44. for k, v := range secret.Data {
  45. t, err := tpl.New(k).
  46. Funcs(tplFuncs).
  47. Parse(string(v))
  48. if err != nil {
  49. log.Error(err, "unable to parse template at key", "key", k)
  50. continue
  51. }
  52. buf := bytes.NewBuffer(nil)
  53. err = t.Execute(buf, data)
  54. if err != nil {
  55. log.Error(err, "unable to execute template at key", "key", k)
  56. continue
  57. }
  58. secret.Data[k] = buf.Bytes()
  59. }
  60. return nil
  61. }
  62. func pkcs12keyPass(pass string, input []byte) []byte {
  63. key, _, err := pkcs12.Decode(input, pass)
  64. if err != nil {
  65. log.Error(err, "unable to decode pkcs12 with password")
  66. return nil
  67. }
  68. kb, err := pkcs8.ConvertPrivateKeyToPKCS8(key)
  69. if err != nil {
  70. log.Error(err, "unable to convert pkcs12 private key")
  71. return nil
  72. }
  73. return kb
  74. }
  75. func pkcs12key(input []byte) []byte {
  76. return pkcs12keyPass("", input)
  77. }
  78. func pkcs12certPass(pass string, input []byte) []byte {
  79. _, cert, err := pkcs12.Decode(input, pass)
  80. if err != nil {
  81. log.Error(err, "unable to decode pkcs12 certificate with password")
  82. return nil
  83. }
  84. return cert.Raw
  85. }
  86. func pkcs12cert(input []byte) []byte {
  87. return pkcs12certPass("", input)
  88. }
  89. func pemPrivateKey(key []byte) string {
  90. buf := bytes.NewBuffer(nil)
  91. err := pem.Encode(buf, &pem.Block{Type: "PRIVATE KEY", Bytes: key})
  92. if err != nil {
  93. log.Error(err, "unable to encode pem private key")
  94. return ""
  95. }
  96. return buf.String()
  97. }
  98. func pemCertificate(cert []byte) string {
  99. buf := bytes.NewBuffer(nil)
  100. err := pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
  101. if err != nil {
  102. log.Error(err, "unable to encode pem certificate")
  103. return ""
  104. }
  105. return buf.String()
  106. }
  107. func base64decode(in []byte) []byte {
  108. out := make([]byte, len(in))
  109. l, err := base64.StdEncoding.Decode(out, in)
  110. if err != nil {
  111. log.Error(err, "unable to encode base64")
  112. return []byte("")
  113. }
  114. return out[:l]
  115. }
  116. func base64encode(in []byte) []byte {
  117. out := make([]byte, base64.StdEncoding.EncodedLen(len(in)))
  118. base64.StdEncoding.Encode(out, in)
  119. return out
  120. }
  121. func fromJSON(in []byte) interface{} {
  122. var out interface{}
  123. err := json.Unmarshal(in, &out)
  124. if err != nil {
  125. log.Error(err, "unable to unmarshal json")
  126. }
  127. return out
  128. }
  129. func toJSON(in interface{}) string {
  130. output, err := json.Marshal(in)
  131. if err != nil {
  132. log.Error(err, "unable to marshal json")
  133. }
  134. return string(output)
  135. }
  136. func toString(in []byte) string {
  137. return string(in)
  138. }
  139. func toBytes(in string) []byte {
  140. return []byte(in)
  141. }