Send complete certificate chain, not just the leaf cert

Also, print a warning when signing may change the issuer.

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
Brad Davidson 2022-05-11 12:43:43 -07:00 committed by Brad Davidson
parent 4df376813d
commit a30741bb53
3 changed files with 52 additions and 5 deletions
factory
storage/kubernetes

View File

@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"os"
"time"
"github.com/rancher/dynamiclistener/cert"
)
@ -16,7 +17,7 @@ func GenCA() (*x509.Certificate, crypto.Signer, error) {
return nil, nil, err
}
caCert, err := NewSelfSignedCACert(caKey, "dynamiclistener-ca", "dynamiclistener-org")
caCert, err := NewSelfSignedCACert(caKey, fmt.Sprintf("dynamiclistener-ca@%d", time.Now().Unix()), "dynamiclistener-org")
if err != nil {
return nil, nil, err
}

View File

@ -154,6 +154,10 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
secret = &v1.Secret{}
}
if err := t.Verify(secret); err != nil {
logrus.Warnf("unable to verify existing certificate: %v - signing operation may change certificate issuer", err)
}
secret = populateCN(secret, cn...)
privateKey, err := getPrivateKey(secret)
@ -171,7 +175,7 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
return nil, false, err
}
certBytes, keyBytes, err := Marshal(newCert, privateKey)
keyBytes, certBytes, err := MarshalChain(privateKey, newCert, t.CACert)
if err != nil {
return nil, false, err
}
@ -187,6 +191,29 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
return secret, true, nil
}
func (t *TLS) Verify(secret *v1.Secret) error {
certsPem := secret.Data[v1.TLSCertKey]
if len(certsPem) == 0 {
return nil
}
certificates, err := cert.ParseCertsPEM(certsPem)
if err != nil || len(certificates) == 0 {
return err
}
verifyOpts := x509.VerifyOptions{
Roots: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{
x509.ExtKeyUsageAny,
},
}
verifyOpts.Roots.AddCert(t.CACert)
_, err = certificates[0].Verify(verifyOpts)
return err
}
func (t *TLS) newCert(domains []string, ips []net.IP, privateKey crypto.Signer) (*x509.Certificate, error) {
return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips)
}
@ -250,14 +277,33 @@ func getPrivateKey(secret *v1.Secret) (crypto.Signer, error) {
return NewPrivateKey()
}
// MarshalChain returns given key and certificates as byte slices.
func MarshalChain(privateKey crypto.Signer, certs ...*x509.Certificate) (keyBytes, certChainBytes []byte, err error) {
keyBytes, err = cert.MarshalPrivateKeyToPEM(privateKey)
if err != nil {
return nil, nil, err
}
for _, cert := range certs {
if cert != nil {
certBlock := pem.Block{
Type: CertificateBlockType,
Bytes: cert.Raw,
}
certChainBytes = append(certChainBytes, pem.EncodeToMemory(&certBlock)...)
}
}
return keyBytes, certChainBytes, nil
}
// Marshal returns the given cert and key as byte slices.
func Marshal(x509Cert *x509.Certificate, privateKey crypto.Signer) ([]byte, []byte, error) {
func Marshal(x509Cert *x509.Certificate, privateKey crypto.Signer) (certBytes, keyBytes []byte, err error) {
certBlock := pem.Block{
Type: CertificateBlockType,
Bytes: x509Cert.Raw,
}
keyBytes, err := cert.MarshalPrivateKeyToPEM(privateKey)
keyBytes, err = cert.MarshalPrivateKeyToPEM(privateKey)
if err != nil {
return nil, nil, err
}

View File

@ -56,7 +56,7 @@ func createAndStoreClientCert(secrets v1controller.SecretClient, namespace strin
return nil, err
}
certPem, keyPem, err := factory.Marshal(cert, key)
keyPem, certPem, err := factory.MarshalChain(key, cert, caCert)
if err != nil {
return nil, err
}