Use a one-use CA to sign temporary certificates

Signed-off-by: James Munnelly <james@munnelly.eu>
This commit is contained in:
James Munnelly 2019-02-25 20:42:44 +00:00
parent 5a10008790
commit dfabece6eb
6 changed files with 53 additions and 8 deletions

View File

@ -111,7 +111,7 @@ func New(ctx *controllerpkg.Context) *Controller {
ctrl.helper = issuer.NewHelper(ctrl.issuerLister, ctrl.clusterIssuerLister)
ctrl.issuerFactory = issuer.NewIssuerFactory(ctx)
ctrl.clock = clock.RealClock{}
ctrl.localTemporarySigner = ctrl.generateTemporaryCertificate
ctrl.localTemporarySigner = generateLocallySignedTemporaryCertificate
return ctrl
}

View File

@ -449,8 +449,8 @@ func isTemporaryCertificate(cert *x509.Certificate) bool {
return cert.SerialNumber.Int64() == staticTemporarySerialNumber
}
func (c *Controller) generateTemporaryCertificate(crt *v1alpha1.Certificate, pk []byte) ([]byte, error) {
template, err := pki.GenerateTemplate(nil, crt)
func generateSelfSignedTemporaryCertificate(crt *v1alpha1.Certificate, pk []byte) ([]byte, error) {
template, err := pki.GenerateTemplate(crt)
template.SerialNumber = big.NewInt(staticTemporarySerialNumber)
signer, err := pki.DecodePrivateKeyBytes(pk)
@ -466,6 +466,52 @@ func (c *Controller) generateTemporaryCertificate(crt *v1alpha1.Certificate, pk
return b, nil
}
// generateLocallySignedTemporaryCertificate signs a temporary certificate for
// the given certificate resource using a one-use temporary CA that is then
// discarded afterwards.
// This is to mitigate a potential attack against x509 certificates that use a
// predictable serial number and weak MD5 hashing algorithms.
// In practice, this shouldn't really be a concern anyway.
func generateLocallySignedTemporaryCertificate(crt *v1alpha1.Certificate, pk []byte) ([]byte, error) {
// generate a throwaway self-signed root CA
caPk, err := pki.GenerateECPrivateKey(pki.ECCurve521)
if err != nil {
return nil, err
}
caCertTemplate, err := pki.GenerateTemplate(&v1alpha1.Certificate{
Spec: v1alpha1.CertificateSpec{
CommonName: "cert-manager.local",
IsCA: true,
},
})
if err != nil {
return nil, err
}
_, caCert, err := pki.SignCertificate(caCertTemplate, caCertTemplate, caPk.Public(), caPk)
if err != nil {
return nil, err
}
// sign a temporary certificate using the root CA
template, err := pki.GenerateTemplate(crt)
if err != nil {
return nil, err
}
template.SerialNumber = big.NewInt(staticTemporarySerialNumber)
signeeKey, err := pki.DecodePrivateKeyBytes(pk)
if err != nil {
return nil, err
}
b, _, err := pki.SignCertificate(template, caCert, signeeKey.Public(), caPk)
if err != nil {
return nil, err
}
return b, nil
}
func (c *Controller) updateCertificateStatus(old, new *v1alpha1.Certificate) (*v1alpha1.Certificate, error) {
if reflect.DeepEqual(old.Status, new.Status) {
return nil, nil

View File

@ -77,7 +77,7 @@ func (c *CA) Issue(ctx context.Context, crt *v1alpha1.Certificate) (*issuer.Issu
}
// generate a x509 certificate template for this Certificate
template, err := pki.GenerateTemplate(c.issuer, crt)
template, err := pki.GenerateTemplate(crt)
if err != nil {
c.Recorder.Eventf(crt, corev1.EventTypeWarning, "ErrorSigning", "Error signing certificate: %v", err)
return nil, err

View File

@ -58,8 +58,7 @@ func generateECDSAPrivateKey(t *testing.T) *ecdsa.PrivateKey {
}
func generateSelfSignedCert(t *testing.T, crt *v1alpha1.Certificate, key crypto.Signer, duration time.Duration) (derBytes, pemBytes []byte) {
selfSignedIssuer := gen.Issuer("test", gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}))
template, err := pki.GenerateTemplate(selfSignedIssuer, crt)
template, err := pki.GenerateTemplate(crt)
if err != nil {
t.Errorf("error generating template: %v", err)
}

View File

@ -57,7 +57,7 @@ func (c *SelfSigned) Issue(ctx context.Context, crt *v1alpha1.Certificate) (*iss
}
// generate a x509 certificate template for this Certificate
template, err := pki.GenerateTemplate(c.issuer, crt)
template, err := pki.GenerateTemplate(crt)
if err != nil {
c.Recorder.Eventf(crt, corev1.EventTypeWarning, "ErrorSigning", "Error signing certificate: %v", err)
return nil, err

View File

@ -145,7 +145,7 @@ func GenerateCSR(issuer v1alpha1.GenericIssuer, crt *v1alpha1.Certificate) (*x50
// This should create a Certificate template that is equivalent to the CertificateRequest
// generated by GenerateCSR.
// The PublicKey field must be populated by the caller.
func GenerateTemplate(issuer v1alpha1.GenericIssuer, crt *v1alpha1.Certificate) (*x509.Certificate, error) {
func GenerateTemplate(crt *v1alpha1.Certificate) (*x509.Certificate, error) {
commonName := CommonNameForCertificate(crt)
dnsNames := DNSNamesForCertificate(crt)
ipAddresses := IPAddressesForCertificate(crt)