connect: Check for expired root cert when cross-signing
This commit is contained in:
parent
2956313f2d
commit
b78f618beb
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue