feat: migrated the operator code to v4

This commit is contained in:
=
2025-08-06 16:28:24 +05:30
parent 13194296c6
commit c12408eb81
184 changed files with 2563 additions and 9880 deletions
+18
View File
@@ -0,0 +1,18 @@
package template
import (
"encoding/base64"
"fmt"
)
func decodeBase64ToBytes(encodedString string) string {
decoded, err := base64.StdEncoding.DecodeString(encodedString)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return string(decoded)
}
func encodeBase64(plainString string) string {
return base64.StdEncoding.EncodeToString([]byte(plainString))
}
+43
View File
@@ -0,0 +1,43 @@
package template
import (
"crypto/x509"
"fmt"
"github.com/lestrrat-go/jwx/v2/jwk"
)
func jwkPublicKeyPem(jwkjson string) string {
k, err := jwk.ParseKey([]byte(jwkjson))
if err != nil {
panic(fmt.Sprintf("[jwkPublicKeyPem] Error: %v", err))
}
var rawkey any
err = k.Raw(&rawkey)
if err != nil {
panic(fmt.Sprintf("[jwkPublicKeyPem] Error: %v", err))
}
mpk, err := x509.MarshalPKIXPublicKey(rawkey)
if err != nil {
panic(fmt.Sprintf("[jwkPublicKeyPem] Error: %v", err))
}
return pemEncode(mpk, "PUBLIC KEY")
}
func jwkPrivateKeyPem(jwkjson string) string {
k, err := jwk.ParseKey([]byte(jwkjson))
if err != nil {
panic(fmt.Sprintf("[jwkPrivateKeyPem] Error: %v", err))
}
var mpk []byte
var pk any
err = k.Raw(&pk)
if err != nil {
panic(fmt.Sprintf("[jwkPrivateKeyPem] Error: %v", err))
}
mpk, err = x509.MarshalPKCS8PrivateKey(pk)
if err != nil {
panic(fmt.Sprintf("[jwkPrivateKeyPem] Error: %v", err))
}
return pemEncode(mpk, "PRIVATE KEY")
}
+98
View File
@@ -0,0 +1,98 @@
package template
import (
"bytes"
"crypto/x509"
"encoding/pem"
"fmt"
"strings"
)
const (
errJunk = "error filtering pem: found junk"
certTypeLeaf = "leaf"
certTypeIntermediate = "intermediate"
certTypeRoot = "root"
)
func filterPEM(pemType, input string) string {
data := []byte(input)
var blocks []byte
var block *pem.Block
var rest []byte
for {
block, rest = pem.Decode(data)
data = rest
if block == nil {
break
}
if !strings.EqualFold(block.Type, pemType) {
continue
}
var buf bytes.Buffer
err := pem.Encode(&buf, block)
if err != nil {
panic(fmt.Sprintf("[filterPEM] Error: %v", err))
}
blocks = append(blocks, buf.Bytes()...)
}
if len(blocks) == 0 && len(rest) != 0 {
panic(fmt.Sprintf("[filterPEM] Error: %v", errJunk))
}
return string(blocks)
}
func filterCertChain(certType, input string) string {
ordered := fetchX509CertChains([]byte(input))
switch certType {
case certTypeLeaf:
cert := ordered[0]
if cert.AuthorityKeyId != nil && !bytes.Equal(cert.AuthorityKeyId, cert.SubjectKeyId) {
return pemEncode(ordered[0].Raw, pemTypeCertificate)
}
case certTypeIntermediate:
if len(ordered) < 2 {
return ""
}
var pemData []byte
for _, cert := range ordered[1:] {
if isRootCertificate(cert) {
break
}
b := &pem.Block{
Type: pemTypeCertificate,
Bytes: cert.Raw,
}
pemData = append(pemData, pem.EncodeToMemory(b)...)
}
return string(pemData)
case certTypeRoot:
cert := ordered[len(ordered)-1]
if isRootCertificate(cert) {
return pemEncode(cert.Raw, pemTypeCertificate)
}
}
return ""
}
func isRootCertificate(cert *x509.Certificate) bool {
return cert.AuthorityKeyId == nil || bytes.Equal(cert.AuthorityKeyId, cert.SubjectKeyId)
}
func pemEncode(thing []byte, kind string) string {
buf := bytes.NewBuffer(nil)
err := pem.Encode(buf, &pem.Block{Type: kind, Bytes: thing})
if err != nil {
panic(fmt.Sprintf("[pemEncode] Error: %v", err))
}
return buf.String()
}
+117
View File
@@ -0,0 +1,117 @@
package template
import (
"bytes"
"crypto/x509"
"encoding/pem"
"fmt"
)
const (
errNilCert = "certificate is nil"
errFoundDisjunctCert = "found multiple leaf or disjunct certificates"
errNoLeafFound = "no leaf certificate found"
errChainCycle = "constructing chain resulted in cycle"
)
type node struct {
cert *x509.Certificate
parent *node
isParent bool
}
func fetchX509CertChains(data []byte) []*x509.Certificate {
var newCertChain []*x509.Certificate
nodes := pemToNodes(data)
// at the end of this computation, the output will be a single linked list
// the tail of the list will be the root node (which has no parents)
// the head of the list will be the leaf node (whose parent will be intermediate certs)
// (head) leaf -> intermediates -> root (tail)
for i := range nodes {
for j := range nodes {
// ignore same node to prevent generating a cycle
if i == j {
continue
}
// if ith node AuthorityKeyId is same as jth node SubjectKeyId, jth node was used
// to sign the ith certificate
if bytes.Equal(nodes[i].cert.AuthorityKeyId, nodes[j].cert.SubjectKeyId) {
nodes[j].isParent = true
nodes[i].parent = nodes[j]
break
}
}
}
var foundLeaf bool
var leaf *node
for i := range nodes {
if !nodes[i].isParent {
if foundLeaf {
panic(fmt.Sprintf("[fetchX509CertChains] Error: %v", errFoundDisjunctCert))
}
// this is the leaf node as it's not a parent for any other node
leaf = nodes[i]
foundLeaf = true
}
}
if leaf == nil {
panic(fmt.Sprintf("[fetchX509CertChains] Error: %v", errNoLeafFound))
}
processedNodes := 0
// iterate through the directed list and append the nodes to new cert chain
for leaf != nil {
processedNodes++
// ensure we aren't stuck in a cyclic loop
if processedNodes > len(nodes) {
panic(fmt.Sprintf("[fetchX509CertChains] Error: %v", errChainCycle))
}
newCertChain = append(newCertChain, leaf.cert)
leaf = leaf.parent
}
return newCertChain
}
func fetchCertChains(data []byte) []byte {
var pemData []byte
newCertChain := fetchX509CertChains(data)
for _, cert := range newCertChain {
b := &pem.Block{
Type: pemTypeCertificate,
Bytes: cert.Raw,
}
pemData = append(pemData, pem.EncodeToMemory(b)...)
}
return pemData
}
func pemToNodes(data []byte) []*node {
nodes := make([]*node, 0)
for {
// decode pem to der first
block, rest := pem.Decode(data)
data = rest
if block == nil {
break
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
panic(fmt.Sprintf("[pemToNodes] Error: %v", err))
}
if cert == nil {
panic(fmt.Sprintf("[pemToNodes] Error: %v", errNilCert))
}
nodes = append(nodes, &node{
cert: cert,
parent: nil,
isParent: false,
})
}
return nodes
}
+144
View File
@@ -0,0 +1,144 @@
package template
import (
"bytes"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
gopkcs12 "software.sslmate.com/src/go-pkcs12"
)
func pkcs12keyPass(pass, input string) string {
privateKey, _, _, err := gopkcs12.DecodeChain([]byte(input), pass)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
marshalPrivateKey, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
var buf bytes.Buffer
if err := pem.Encode(&buf, &pem.Block{
Type: pemTypeKey,
Bytes: marshalPrivateKey,
}); err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return buf.String()
}
func parsePrivateKey(block []byte) any {
if k, err := x509.ParsePKCS1PrivateKey(block); err == nil {
return k
}
if k, err := x509.ParsePKCS8PrivateKey(block); err == nil {
return k
}
if k, err := x509.ParseECPrivateKey(block); err == nil {
return k
}
panic("Error: unable to parse private key")
}
func pkcs12key(input string) string {
return pkcs12keyPass("", input)
}
func pkcs12certPass(pass, input string) string {
_, certificate, caCerts, err := gopkcs12.DecodeChain([]byte(input), pass)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
var pemData []byte
var buf bytes.Buffer
if err := pem.Encode(&buf, &pem.Block{
Type: pemTypeCertificate,
Bytes: certificate.Raw,
}); err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
pemData = append(pemData, buf.Bytes()...)
for _, ca := range caCerts {
var buf bytes.Buffer
if err := pem.Encode(&buf, &pem.Block{
Type: pemTypeCertificate,
Bytes: ca.Raw,
}); err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
pemData = append(pemData, buf.Bytes()...)
}
// try to order certificate chain. If it fails we return
// the unordered raw pem data.
// This fails if multiple leaf or disjunct certs are provided.
ordered := fetchCertChains(pemData)
return string(ordered)
}
func pkcs12cert(input string) string {
return pkcs12certPass("", input)
}
func pemToPkcs12(cert, key string) string {
return pemToPkcs12Pass(cert, key, "")
}
func pemToPkcs12Pass(cert, key, pass string) string {
certPem, _ := pem.Decode([]byte(cert))
parsedCert, err := x509.ParseCertificate(certPem.Bytes)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return certsToPkcs12(parsedCert, key, nil, pass)
}
func fullPemToPkcs12(cert, key string) string {
return fullPemToPkcs12Pass(cert, key, "")
}
func fullPemToPkcs12Pass(cert, key, pass string) string {
certPem, rest := pem.Decode([]byte(cert))
parsedCert, err := x509.ParseCertificate(certPem.Bytes)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
caCerts := make([]*x509.Certificate, 0)
for len(rest) > 0 {
caPem, restBytes := pem.Decode(rest)
rest = restBytes
caCert, err := x509.ParseCertificate(caPem.Bytes)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
caCerts = append(caCerts, caCert)
}
return certsToPkcs12(parsedCert, key, caCerts, pass)
}
func certsToPkcs12(cert *x509.Certificate, key string, caCerts []*x509.Certificate, password string) string {
keyPem, _ := pem.Decode([]byte(key))
parsedKey := parsePrivateKey(keyPem.Bytes)
pfx, err := gopkcs12.Modern.Encode(parsedKey, cert, caCerts, password)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return base64.StdEncoding.EncodeToString(pfx)
}
+67
View File
@@ -0,0 +1,67 @@
package template
import (
tpl "text/template"
"github.com/Masterminds/sprig/v3"
)
var customInfisicalSecretTemplateFunctions = tpl.FuncMap{
"pkcs12key": pkcs12key,
"pkcs12keyPass": pkcs12keyPass,
"pkcs12cert": pkcs12cert,
"pkcs12certPass": pkcs12certPass,
"pemToPkcs12": pemToPkcs12,
"pemToPkcs12Pass": pemToPkcs12Pass,
"fullPemToPkcs12": fullPemToPkcs12,
"fullPemToPkcs12Pass": fullPemToPkcs12Pass,
"filterPEM": filterPEM,
"filterCertChain": filterCertChain,
"jwkPublicKeyPem": jwkPublicKeyPem,
"jwkPrivateKeyPem": jwkPrivateKeyPem,
"toYaml": toYAML,
"fromYaml": fromYAML,
"decodeBase64ToBytes": decodeBase64ToBytes,
"encodeBase64": encodeBase64,
}
const (
errParse = "unable to parse template at key %s: %s"
errExecute = "unable to execute template at key %s: %s"
errDecodePKCS12WithPass = "unable to decode pkcs12 with password: %s"
errDecodeCertWithPass = "unable to decode pkcs12 certificate with password: %s"
errParsePrivKey = "unable to parse private key type"
errUnmarshalJSON = "unable to unmarshal json: %s"
errMarshalJSON = "unable to marshal json: %s"
pemTypeCertificate = "CERTIFICATE"
pemTypeKey = "PRIVATE KEY"
)
func InitializeTemplateFunctions() {
templates := customInfisicalSecretTemplateFunctions
sprigFuncs := sprig.TxtFuncMap()
// removed for security reasons
delete(sprigFuncs, "env")
delete(sprigFuncs, "expandenv")
for k, v := range sprigFuncs {
// make sure we aren't overwriting any of our own functions
_, exists := templates[k]
if !exists {
templates[k] = v
}
}
customInfisicalSecretTemplateFunctions = templates
}
func GetTemplateFunctions() tpl.FuncMap {
return customInfisicalSecretTemplateFunctions
}
+30
View File
@@ -0,0 +1,30 @@
package template
import (
"fmt"
"strings"
"gopkg.in/yaml.v3"
)
func toYAML(v any) string {
data, err := yaml.Marshal(v)
if err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return strings.TrimSuffix(string(data), "\n")
}
// fromYAML converts a YAML document into a map[string]any.
//
// This is not a general-purpose YAML parser, and will not parse all valid
// YAML documents.
func fromYAML(str string) map[string]any {
mapData := map[string]any{}
if err := yaml.Unmarshal([]byte(str), &mapData); err != nil {
panic(fmt.Sprintf("Error: %v", err))
}
return mapData
}