diff --git a/authority/tls.go b/authority/tls.go index 03999f77..ad5ea808 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -30,8 +30,9 @@ type SignOptions struct { } var ( - stepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64} - stepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(stepOIDRoot, 1)...) + stepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64} + stepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(stepOIDRoot, 1)...) + oidAuthorityKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 35} ) type stepProvisionerASN1 struct { @@ -190,8 +191,6 @@ func (a *Authority) Renew(ocx *x509.Certificate) (*x509.Certificate, *x509.Certi NotBefore: now, NotAfter: now.Add(duration), KeyUsage: oldCert.KeyUsage, - Extensions: oldCert.Extensions, - ExtraExtensions: oldCert.ExtraExtensions, UnhandledCriticalExtensions: oldCert.UnhandledCriticalExtensions, ExtKeyUsage: oldCert.ExtKeyUsage, UnknownExtKeyUsage: oldCert.UnknownExtKeyUsage, @@ -218,6 +217,15 @@ func (a *Authority) Renew(ocx *x509.Certificate) (*x509.Certificate, *x509.Certi PolicyIdentifiers: oldCert.PolicyIdentifiers, } + // Copy all extensions except for Authority Key Identifier. This one might + // be different if we rotate the intermediate certificate and it will cause + // a TLS bad certificate error. + for _, ext := range oldCert.Extensions { + if !ext.Id.Equal(oidAuthorityKeyIdentifier) { + newCert.ExtraExtensions = append(newCert.ExtraExtensions, ext) + } + } + leaf, err := x509util.NewLeafProfileWithTemplate(newCert, issIdentity.Crt, issIdentity.Key) if err != nil { diff --git a/authority/tls_test.go b/authority/tls_test.go index 22b0deba..cf8852f4 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/http" + "reflect" "testing" "time" @@ -269,7 +270,8 @@ func TestRenew(t *testing.T) { a.intermediateIdentity.Key, x509util.WithNotBeforeAfterDuration(so.NotBefore, so.NotAfter, 0), withDefaultASN1DN(a.config.AuthorityConfig.Template), - x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test")) + x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test"), + withProvisionerOID("Max", a.config.AuthorityConfig.Provisioners[0].Key.KeyID)) assert.FatalError(t, err) crtBytes, err := leaf.CreateCertificate() assert.FatalError(t, err) @@ -390,6 +392,20 @@ func TestRenew(t *testing.T) { realIntermediate, err := x509.ParseCertificate(a.intermediateIdentity.Crt.Raw) assert.FatalError(t, err) assert.Equals(t, intermediate, realIntermediate) + + // Compare extensions: they can be in a different order + for _, ext1 := range crt.Extensions { + found := false + for _, ext2 := range leaf.Extensions { + if reflect.DeepEqual(ext1, ext2) { + found = true + break + } + } + if !found { + t.Errorf("x509 extension %s not found in renewed certificate", ext1.Id.String()) + } + } } } })