2023-03-25 15:06:58 -05:00

75 lines
2.0 KiB
Go

package certificate
import (
"bytes"
"fmt"
"strconv"
"time"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
)
func SignCert(caCertPem, caPrivKeyPem, csrPem string) (string, error) {
caCertData, _ := pem.Decode([]byte(caCertPem))
caCert, err := x509.ParseCertificate(caCertData.Bytes)
if err != nil {
return "", fmt.Errorf("parse cert %v", err)
}
pemKey, _ := pem.Decode([]byte(caPrivKeyPem))
if pemKey == nil || pemKey.Type != "RSA PRIVATE KEY" {
return "", fmt.Errorf("failed to decode PEM block containing private key")
}
keyPair, err := x509.ParsePKCS1PrivateKey(pemKey.Bytes)
if err != nil {
return "", fmt.Errorf("private key %v", err)
}
csrData, _ := pem.Decode([]byte(csrPem))
csr, err := x509.ParseCertificateRequest(csrData.Bytes)
if err != nil {
return "", fmt.Errorf("parse csr %v", err)
}
serial, _ := strconv.ParseInt(time.Now().Format("20060102150405"), 10, 64)
certTemplate := x509.Certificate{
SerialNumber: big.NewInt(serial + 1),
Issuer: caCert.Issuer,
Subject: pkix.Name{
Organization: []string{"Kubernetes Mutating Webserver"},
Country: csr.Subject.Country,
Province: []string{"Cluster Service"},
Locality: []string{"Cluster Local"},
StreetAddress: csr.Subject.StreetAddress,
PostalCode: csr.Subject.PostalCode,
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(1, 6, 0),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
},
DNSNames: csr.DNSNames,
Signature: csr.Signature,
SignatureAlgorithm: csr.SignatureAlgorithm,
PublicKey: csr.PublicKey,
PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &certTemplate, caCert, csr.PublicKey, keyPair)
if err != nil {
return "", fmt.Errorf("sign %v", err)
}
c := new(bytes.Buffer)
pem.Encode(c, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})
return c.String(), nil
}