mirror of https://github.com/status-im/consul.git
ca: improve RenewIntermediate tests
Use the new verifyLearfCert to show the cert verifies with intermediates from both sources. This required using the RPC interface so that the leaf pem was constructed correctly. Add IndexedCARoots.Active since that is a common operation we see in a few places.
This commit is contained in:
parent
a4ba1f348d
commit
2e4e8bd791
|
@ -57,8 +57,6 @@ func TestCAManager_Initialize_Vault_Secondary_SharedVault(t *testing.T) {
|
||||||
testrpc.WaitForTestAgent(t, serverDC1.RPC, "dc1")
|
testrpc.WaitForTestAgent(t, serverDC1.RPC, "dc1")
|
||||||
|
|
||||||
codec := rpcClient(t, serverDC1)
|
codec := rpcClient(t, serverDC1)
|
||||||
defer codec.Close()
|
|
||||||
|
|
||||||
roots := structs.IndexedCARoots{}
|
roots := structs.IndexedCARoots{}
|
||||||
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -87,8 +85,6 @@ func TestCAManager_Initialize_Vault_Secondary_SharedVault(t *testing.T) {
|
||||||
testrpc.WaitForActiveCARoot(t, serverDC2.RPC, "dc2", nil)
|
testrpc.WaitForActiveCARoot(t, serverDC2.RPC, "dc2", nil)
|
||||||
|
|
||||||
codec := rpcClient(t, serverDC2)
|
codec := rpcClient(t, serverDC2)
|
||||||
defer codec.Close()
|
|
||||||
|
|
||||||
roots := structs.IndexedCARoots{}
|
roots := structs.IndexedCARoots{}
|
||||||
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -420,8 +420,13 @@ func TestCAManager_RenewIntermediate_Vault_Primary(t *testing.T) {
|
||||||
intermediatePEM = newIntermediatePEM
|
intermediatePEM = newIntermediatePEM
|
||||||
})
|
})
|
||||||
|
|
||||||
_, activeRoot, err = store.CARootActive(nil)
|
codec := rpcClient(t, s1)
|
||||||
|
roots := structs.IndexedCARoots{}
|
||||||
|
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
require.Len(roots.Roots, 1)
|
||||||
|
|
||||||
|
activeRoot = roots.Active()
|
||||||
require.Equal(intermediatePEM, s1.caManager.getLeafSigningCertFromRoot(activeRoot))
|
require.Equal(intermediatePEM, s1.caManager.getLeafSigningCertFromRoot(activeRoot))
|
||||||
require.Equal(connect.HexString(intermediateCert.SubjectKeyId), activeRoot.SigningKeyID)
|
require.Equal(connect.HexString(intermediateCert.SubjectKeyId), activeRoot.SigningKeyID)
|
||||||
|
|
||||||
|
@ -431,36 +436,18 @@ func TestCAManager_RenewIntermediate_Vault_Primary(t *testing.T) {
|
||||||
|
|
||||||
// Have the new intermediate sign a leaf cert and make sure the chain is correct.
|
// Have the new intermediate sign a leaf cert and make sure the chain is correct.
|
||||||
spiffeService := &connect.SpiffeIDService{
|
spiffeService := &connect.SpiffeIDService{
|
||||||
Host: "node1",
|
Host: roots.TrustDomain,
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Datacenter: "dc1",
|
Datacenter: "dc1",
|
||||||
Service: "foo",
|
Service: "foo",
|
||||||
}
|
}
|
||||||
raw, _ := connect.TestCSR(t, spiffeService)
|
csr, _ := connect.TestCSR(t, spiffeService)
|
||||||
|
|
||||||
leafCsr, err := connect.ParseCSR(raw)
|
req := structs.CASignRequest{CSR: csr}
|
||||||
require.NoError(err)
|
cert := structs.IssuedCert{}
|
||||||
|
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Sign", &req, &cert)
|
||||||
leafPEM, err := provider.Sign(leafCsr)
|
|
||||||
require.NoError(err)
|
|
||||||
|
|
||||||
cert, err := connect.ParseCert(leafPEM)
|
|
||||||
require.NoError(err)
|
|
||||||
|
|
||||||
// Check that the leaf signed by the new intermediate can be verified using the
|
|
||||||
// returned cert chain (signed intermediate + remote root).
|
|
||||||
intermediatePool := x509.NewCertPool()
|
|
||||||
// TODO: do not explicitly add the intermediatePEM, we should have it available
|
|
||||||
// from leafPEM. Use connect.ParseLeafCerts to do the right thing.
|
|
||||||
intermediatePool.AppendCertsFromPEM([]byte(intermediatePEM))
|
|
||||||
rootPool := x509.NewCertPool()
|
|
||||||
rootPool.AppendCertsFromPEM([]byte(caRoot.RootCert))
|
|
||||||
|
|
||||||
_, err = cert.Verify(x509.VerifyOptions{
|
|
||||||
Intermediates: intermediatePool,
|
|
||||||
Roots: rootPool,
|
|
||||||
})
|
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
verifyLeafCert(t, caRoot, cert.CertPEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCAManager_RenewIntermediate_Secondary(t *testing.T) {
|
func TestCAManager_RenewIntermediate_Secondary(t *testing.T) {
|
||||||
|
@ -570,47 +557,31 @@ func TestCAManager_RenewIntermediate_Secondary(t *testing.T) {
|
||||||
intermediateCert = cert
|
intermediateCert = cert
|
||||||
})
|
})
|
||||||
|
|
||||||
|
codec := rpcClient(t, s2)
|
||||||
|
roots := structs.IndexedCARoots{}
|
||||||
|
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
|
||||||
|
require.NoError(err)
|
||||||
|
require.Len(roots.Roots, 1)
|
||||||
|
|
||||||
_, activeRoot, err = store.CARootActive(nil)
|
_, activeRoot, err = store.CARootActive(nil)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
require.Equal(intermediatePEM, s2.caManager.getLeafSigningCertFromRoot(activeRoot))
|
require.Equal(intermediatePEM, s2.caManager.getLeafSigningCertFromRoot(activeRoot))
|
||||||
require.Equal(connect.HexString(intermediateCert.SubjectKeyId), activeRoot.SigningKeyID)
|
require.Equal(connect.HexString(intermediateCert.SubjectKeyId), activeRoot.SigningKeyID)
|
||||||
|
|
||||||
// Get the root from dc1 and validate a chain of:
|
|
||||||
// dc2 leaf -> dc2 intermediate -> dc1 root
|
|
||||||
_, caRoot := getCAProviderWithLock(s1)
|
|
||||||
|
|
||||||
// Have dc2 sign a leaf cert and make sure the chain is correct.
|
// Have dc2 sign a leaf cert and make sure the chain is correct.
|
||||||
spiffeService := &connect.SpiffeIDService{
|
spiffeService := &connect.SpiffeIDService{
|
||||||
Host: "node1",
|
Host: roots.TrustDomain,
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Datacenter: "dc1",
|
Datacenter: "dc2",
|
||||||
Service: "foo",
|
Service: "foo",
|
||||||
}
|
}
|
||||||
raw, _ := connect.TestCSR(t, spiffeService)
|
csr, _ := connect.TestCSR(t, spiffeService)
|
||||||
|
|
||||||
leafCsr, err := connect.ParseCSR(raw)
|
req := structs.CASignRequest{CSR: csr}
|
||||||
require.NoError(err)
|
cert := structs.IssuedCert{}
|
||||||
|
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Sign", &req, &cert)
|
||||||
leafPEM, err := secondaryProvider.Sign(leafCsr)
|
|
||||||
require.NoError(err)
|
|
||||||
|
|
||||||
intermediateCert, err = connect.ParseCert(leafPEM)
|
|
||||||
require.NoError(err)
|
|
||||||
|
|
||||||
// Check that the leaf signed by the new intermediate can be verified using the
|
|
||||||
// returned cert chain (signed intermediate + remote root).
|
|
||||||
intermediatePool := x509.NewCertPool()
|
|
||||||
// TODO: do not explicitly add the intermediatePEM, we should have it available
|
|
||||||
// from leafPEM. Use connect.ParseLeafCerts to do the right thing.
|
|
||||||
intermediatePool.AppendCertsFromPEM([]byte(intermediatePEM))
|
|
||||||
rootPool := x509.NewCertPool()
|
|
||||||
rootPool.AppendCertsFromPEM([]byte(caRoot.RootCert))
|
|
||||||
|
|
||||||
_, err = intermediateCert.Verify(x509.VerifyOptions{
|
|
||||||
Intermediates: intermediatePool,
|
|
||||||
Roots: rootPool,
|
|
||||||
})
|
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
verifyLeafCert(t, activeRoot, cert.CertPEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConnectCA_ConfigurationSet_RootRotation_Secondary(t *testing.T) {
|
func TestConnectCA_ConfigurationSet_RootRotation_Secondary(t *testing.T) {
|
||||||
|
|
|
@ -55,6 +55,15 @@ type IndexedCARoots struct {
|
||||||
QueryMeta `json:"-"`
|
QueryMeta `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r IndexedCARoots) Active() *CARoot {
|
||||||
|
for _, root := range r.Roots {
|
||||||
|
if root.ID == r.ActiveRootID {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CARoot represents a root CA certificate that is trusted.
|
// CARoot represents a root CA certificate that is trusted.
|
||||||
type CARoot struct {
|
type CARoot struct {
|
||||||
// ID is a globally unique ID (UUID) representing this CA root.
|
// ID is a globally unique ID (UUID) representing this CA root.
|
||||||
|
|
Loading…
Reference in New Issue