migration to new secrets nearly complete
This commit is contained in:
178
cmd/dkl-local-server/tls-ca.go
Normal file
178
cmd/dkl-local-server/tls-ca.go
Normal file
@ -0,0 +1,178 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/csr"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/initca"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
)
|
||||
|
||||
type CA struct {
|
||||
Key []byte
|
||||
Cert []byte
|
||||
|
||||
Signed map[string]*KeyCert
|
||||
}
|
||||
|
||||
func (ca *CA) Init() (err error) {
|
||||
req := ca.newReq()
|
||||
|
||||
cert, _, key, err := initca.New(req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("initca: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
ca.Key = key
|
||||
ca.Cert = cert
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ca *CA) RenewCert() (err error) {
|
||||
var signer crypto.Signer
|
||||
signer, err = helpers.ParsePrivateKeyPEM(ca.Key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
newCert, _, err := initca.NewFromSigner(ca.newReq(), signer)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ca.Cert = newCert
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_ CA) newReq() *csr.CertificateRequest {
|
||||
return &csr.CertificateRequest{
|
||||
CN: "Direktil Local Server",
|
||||
KeyRequest: &csr.KeyRequest{
|
||||
A: "ecdsa",
|
||||
S: 521, // 256, 384, 521
|
||||
},
|
||||
Names: []csr.Name{
|
||||
{
|
||||
O: "novit.io",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (ca CA) Signer(policy *config.Signing) (result *local.Signer, err error) {
|
||||
caCert, err := helpers.ParseCertificatePEM(ca.Cert)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
caKey, err := helpers.ParsePrivateKeyPEM(ca.Key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return local.NewSigner(caKey, caCert, signer.DefaultSigAlgo(caKey), policy)
|
||||
}
|
||||
|
||||
func getUsableKeyCert(cluster, caName, name, profile, label string, req *csr.CertificateRequest, cfg *config.Config) (kc KeyCert, err error) {
|
||||
log := log.New(log.Default().Writer(), cluster+": CA "+caName+": ", log.Flags()|log.Lmsgprefix)
|
||||
|
||||
ca, err := getUsableClusterCA(cluster, caName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, host := range req.Hosts {
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
// valid IP (v4 or v6)
|
||||
continue
|
||||
}
|
||||
|
||||
if host == "*" {
|
||||
continue
|
||||
}
|
||||
|
||||
if errs := validation.IsDNS1123Subdomain(host); len(errs) == 0 {
|
||||
continue
|
||||
}
|
||||
if errs := validation.IsWildcardDNS1123Subdomain(host); len(errs) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
err = fmt.Errorf("%q is not an IP or FQDN", host)
|
||||
return
|
||||
}
|
||||
|
||||
if req.CA != nil {
|
||||
err = errors.New("no CA section allowed here")
|
||||
return
|
||||
}
|
||||
|
||||
rh := hash(req)
|
||||
|
||||
key := cluster + "/" + caName + "/" + name
|
||||
|
||||
kc, found, err := clusterCASignedKeys.Get(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if found {
|
||||
if rh == kc.ReqHash {
|
||||
err = checkCertUsable(kc.Cert)
|
||||
if err == nil {
|
||||
return // all good, no need to create or renew
|
||||
}
|
||||
|
||||
log.Print("regenerating certificate: ", err)
|
||||
|
||||
} else {
|
||||
log.Printf("CSR changed for %s: hash=%q previous=%q", name, rh, kc.ReqHash)
|
||||
}
|
||||
} else {
|
||||
log.Print("new CSR for ", name)
|
||||
}
|
||||
|
||||
sgr, err := ca.Signer(cfg.Signing)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
generator := &csr.Generator{Validator: func(_ *csr.CertificateRequest) error { return nil }}
|
||||
|
||||
csr, tlsKey, err := generator.ProcessRequest(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signReq := signer.SignRequest{
|
||||
Request: string(csr),
|
||||
Profile: profile,
|
||||
Label: label,
|
||||
}
|
||||
|
||||
cert, err := sgr.Sign(signReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
kc = KeyCert{
|
||||
Key: tlsKey,
|
||||
Cert: cert,
|
||||
ReqHash: rh,
|
||||
}
|
||||
|
||||
err = clusterCASignedKeys.Put(key, kc)
|
||||
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user