connect: Check for expired root cert when cross-signing

This commit is contained in:
Kyle Havlovitz 2020-10-09 04:35:42 -07:00
parent 2956313f2d
commit b78f618beb
4 changed files with 24 additions and 9 deletions

View File

@ -21,14 +21,13 @@ import (
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
) )
const ( var (
// NotBefore will be CertificateTimeDriftBuffer in the past to account for // NotBefore will be CertificateTimeDriftBuffer in the past to account for
// time drift between different servers. // time drift between different servers.
CertificateTimeDriftBuffer = time.Minute CertificateTimeDriftBuffer = time.Minute
)
var ErrNotInitialized = errors.New("provider not initialized") ErrNotInitialized = errors.New("provider not initialized")
)
type ConsulProvider struct { type ConsulProvider struct {
Delegate ConsulProviderStateDelegate Delegate ConsulProviderStateDelegate

View File

@ -9,6 +9,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
"time"
"github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
@ -476,8 +477,20 @@ func (v *VaultProvider) SignIntermediate(csr *x509.CertificateRequest) (string,
// CrossSignCA takes a CA certificate and cross-signs it to form a trust chain // CrossSignCA takes a CA certificate and cross-signs it to form a trust chain
// back to our active root. // back to our active root.
func (v *VaultProvider) CrossSignCA(cert *x509.Certificate) (string, error) { func (v *VaultProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
rootPEM, err := v.ActiveRoot()
if err != nil {
return "", err
}
rootCert, err := connect.ParseCert(rootPEM)
if err != nil {
return "", fmt.Errorf("error parsing root cert: %v", err)
}
if rootCert.NotAfter.Before(time.Now()) {
return "", fmt.Errorf("root certificate is expired")
}
var pemBuf bytes.Buffer var pemBuf bytes.Buffer
err := pem.Encode(&pemBuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) err = pem.Encode(&pemBuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -516,6 +516,7 @@ func (s *Server) persistNewRoot(provider ca.Provider, newActiveRoot *structs.CAR
// which means it must never take that lock itself or call anything that does. // which means it must never take that lock itself or call anything that does.
func (s *Server) getIntermediateCAPrimary(provider ca.Provider, newActiveRoot *structs.CARoot) error { func (s *Server) getIntermediateCAPrimary(provider ca.Provider, newActiveRoot *structs.CARoot) error {
connectLogger := s.loggers.Named(logging.Connect) connectLogger := s.loggers.Named(logging.Connect)
// Generate and sign an intermediate cert using the root CA.
intermediatePEM, err := provider.GenerateIntermediate() intermediatePEM, err := provider.GenerateIntermediate()
if err != nil { if err != nil {
return fmt.Errorf("error generating new intermediate cert: %v", err) return fmt.Errorf("error generating new intermediate cert: %v", err)
@ -531,7 +532,7 @@ func (s *Server) getIntermediateCAPrimary(provider ca.Provider, newActiveRoot *s
newActiveRoot.IntermediateCerts = append(newActiveRoot.IntermediateCerts, intermediatePEM) newActiveRoot.IntermediateCerts = append(newActiveRoot.IntermediateCerts, intermediatePEM)
newActiveRoot.SigningKeyID = connect.EncodeSigningKeyID(intermediateCert.SubjectKeyId) newActiveRoot.SigningKeyID = connect.EncodeSigningKeyID(intermediateCert.SubjectKeyId)
connectLogger.Info("generated new intermediate certificate in primary datacenter") connectLogger.Info("generated new intermediate certificate for primary datacenter")
return nil return nil
} }
@ -738,7 +739,6 @@ func (s *Server) intermediateCertRenewalWatch(ctx context.Context) error {
if lessThanHalfTimePassed(time.Now(), intermediateCert.NotBefore.Add(ca.CertificateTimeDriftBuffer), if lessThanHalfTimePassed(time.Now(), intermediateCert.NotBefore.Add(ca.CertificateTimeDriftBuffer),
intermediateCert.NotAfter) { intermediateCert.NotAfter) {
//connectLogger.Info("checked time passed", intermediateCert.NotBefore.Add(ca.CertificateTimeDriftBuffer), intermediateCert.NotAfter)
return nil return nil
} }

View File

@ -185,11 +185,14 @@ func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
// no parallel execution because we change globals // no parallel execution because we change globals
origInterval := structs.IntermediateCertRenewInterval origInterval := structs.IntermediateCertRenewInterval
origMinTTL := structs.MinLeafCertTTL origMinTTL := structs.MinLeafCertTTL
origDriftBuffer := ca.CertificateTimeDriftBuffer
defer func() { defer func() {
structs.IntermediateCertRenewInterval = origInterval structs.IntermediateCertRenewInterval = origInterval
structs.MinLeafCertTTL = origMinTTL structs.MinLeafCertTTL = origMinTTL
ca.CertificateTimeDriftBuffer = origDriftBuffer
}() }()
ca.CertificateTimeDriftBuffer = 30 * time.Second
structs.IntermediateCertRenewInterval = time.Millisecond structs.IntermediateCertRenewInterval = time.Millisecond
structs.MinLeafCertTTL = time.Second structs.MinLeafCertTTL = time.Second
require := require.New(t) require := require.New(t)
@ -207,7 +210,7 @@ func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
"Token": testVault.RootToken, "Token": testVault.RootToken,
"RootPKIPath": "pki-root/", "RootPKIPath": "pki-root/",
"IntermediatePKIPath": "pki-intermediate/", "IntermediatePKIPath": "pki-intermediate/",
"LeafCertTTL": "5s", "LeafCertTTL": "1s",
// The retry loop only retries for 7sec max and // The retry loop only retries for 7sec max and
// the ttl needs to be below so that it // the ttl needs to be below so that it
// triggers definitely. // triggers definitely.
@ -215,7 +218,7 @@ func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
// valid from 1minute in the past, we need to // valid from 1minute in the past, we need to
// account for that, otherwise it will be // account for that, otherwise it will be
// expired immediately. // expired immediately.
"IntermediateCertTTL": "15s", "IntermediateCertTTL": "5s",
}, },
} }
}) })