Skip to content

Commit

Permalink
ca: add test cases for rotating external trusted CA
Browse files Browse the repository at this point in the history
  • Loading branch information
dnephin committed Feb 8, 2022
1 parent bc0ace6 commit a802aab
Showing 1 changed file with 85 additions and 23 deletions.
108 changes: 85 additions & 23 deletions agent/consul/leader_connect_ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,25 @@ func TestCAManager_Initialize_Vault_Secondary_SharedVault(t *testing.T) {
}

func verifyLeafCert(t *testing.T, root *structs.CARoot, leafCertPEM string) {
t.Helper()
roots := structs.IndexedCARoots{
ActiveRootID: root.ID,
Roots: []*structs.CARoot{root},
}
verifyLeafCertWithRoots(t, roots, leafCertPEM)
}

func verifyLeafCertWithRoots(t *testing.T, roots structs.IndexedCARoots, leafCertPEM string) {
t.Helper()
leaf, intermediates, err := connect.ParseLeafCerts(leafCertPEM)
require.NoError(t, err)

pool := x509.NewCertPool()
ok := pool.AppendCertsFromPEM([]byte(root.RootCert))
if !ok {
t.Fatalf("Failed to add root CA PEM to cert pool")
for _, r := range roots.Roots {
ok := pool.AppendCertsFromPEM([]byte(r.RootCert))
if !ok {
t.Fatalf("Failed to add root CA PEM to cert pool")
}
}

// verify with intermediates from leaf CertPEM
Expand All @@ -118,10 +129,12 @@ func verifyLeafCert(t *testing.T, root *structs.CARoot, leafCertPEM string) {

// verify with intermediates from the CARoot
intermediates = x509.NewCertPool()
for _, intermediate := range root.IntermediateCerts {
c, err := connect.ParseCert(intermediate)
require.NoError(t, err)
intermediates.AddCert(c)
for _, r := range roots.Roots {
for _, intermediate := range r.IntermediateCerts {
c, err := connect.ParseCert(intermediate)
require.NoError(t, err)
intermediates.AddCert(c)
}
}

_, err = leaf.Verify(x509.VerifyOptions{
Expand Down Expand Up @@ -628,10 +641,6 @@ func TestCAManager_Initialize_Vault_WithIntermediateAsPrimaryCA(t *testing.T) {
"Token": vault.RootToken,
"RootPKIPath": meshRootPath,
"IntermediatePKIPath": "pki-intermediate/",
// TODO: there are failures to init the CA system if these are not set
// to the values of the already initialized CA.
"PrivateKeyType": "ec",
"PrivateKeyBits": 256,
},
}
})
Expand Down Expand Up @@ -664,10 +673,6 @@ func TestCAManager_Initialize_Vault_WithIntermediateAsPrimaryCA(t *testing.T) {
"Token": vault.RootToken,
"RootPKIPath": meshRootPath,
"IntermediatePKIPath": "pki-secondary/",
// TODO: there are failures to init the CA system if these are not set
// to the values of the already initialized CA.
"PrivateKeyType": "ec",
"PrivateKeyBits": 256,
},
}
})
Expand Down Expand Up @@ -727,10 +732,6 @@ func TestCAManager_Initialize_Vault_WithExternalTrustedCA(t *testing.T) {
"Token": vault.RootToken,
"RootPKIPath": primaryCAPath,
"IntermediatePKIPath": "pki-intermediate/",
// TODO: there are failures to init the CA system if these are not set
// to the values of the already initialized CA.
"PrivateKeyType": "ec",
"PrivateKeyBits": 256,
},
}
})
Expand Down Expand Up @@ -765,15 +766,12 @@ func TestCAManager_Initialize_Vault_WithExternalTrustedCA(t *testing.T) {
}
})

// TODO: renew primary leaf signing cert
// TODO: rotate root

runStep(t, "start secondary DC", func(t *testing.T) {
joinWAN(t, serverDC2, serverDC1)
testrpc.WaitForActiveCARoot(t, serverDC2.RPC, "dc2", nil)

codec := rpcClient(t, serverDC2)
roots := structs.IndexedCARoots{}
roots = structs.IndexedCARoots{}
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
require.NoError(t, err)
require.Len(t, roots.Roots, 1)
Expand All @@ -788,6 +786,7 @@ func TestCAManager_Initialize_Vault_WithExternalTrustedCA(t *testing.T) {
renewLeafSigningCert(t, serverDC1.caManager, serverDC1.caManager.primaryRenewIntermediate)

codec := rpcClient(t, serverDC1)
roots = structs.IndexedCARoots{}
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
require.NoError(t, err)
require.Len(t, roots.Roots, 1)
Expand All @@ -809,6 +808,7 @@ func TestCAManager_Initialize_Vault_WithExternalTrustedCA(t *testing.T) {
renewLeafSigningCert(t, serverDC2.caManager, serverDC2.caManager.secondaryRequestNewSigningCert)

codec := rpcClient(t, serverDC2)
roots = structs.IndexedCARoots{}
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
require.NoError(t, err)
require.Len(t, roots.Roots, 1)
Expand All @@ -824,6 +824,68 @@ func TestCAManager_Initialize_Vault_WithExternalTrustedCA(t *testing.T) {
// original certs from old signing cert should still verify
verifyLeafCert(t, roots.Roots[0], origLeaf)
})

runStep(t, "rotate root by changing the provider", func(t *testing.T) {
codec := rpcClient(t, serverDC1)
req := &structs.CARequest{
Op: structs.CAOpSetConfig,
Config: &structs.CAConfiguration{
Provider: "consul",
},
}
var resp error
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.ConfigurationSet", req, &resp)
require.NoError(t, err)
require.Nil(t, resp)

roots = structs.IndexedCARoots{}
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
require.NoError(t, err)
require.Len(t, roots.Roots, 2)
active := roots.Active()
require.Len(t, active.IntermediateCerts, 1)

leafPEM := getLeafCert(t, codec, roots.TrustDomain, "dc1")
verifyLeafCert(t, roots.Active(), leafPEM)

// original certs from old root cert should still verify
verifyLeafCertWithRoots(t, roots, origLeaf)
})

runStep(t, "rotate to a different external root", func(t *testing.T) {
setupPrimaryCA(t, vclient, "pki-primary-2/", rootPEM)

codec := rpcClient(t, serverDC1)
req := &structs.CARequest{
Op: structs.CAOpSetConfig,
Config: &structs.CAConfiguration{
Provider: "vault",
Config: map[string]interface{}{
"Address": vault.Addr,
"Token": vault.RootToken,
"RootPKIPath": "pki-primary-2/",
"IntermediatePKIPath": "pki-intermediate-2/",
},
},
}
var resp error
err := msgpackrpc.CallWithCodec(codec, "ConnectCA.ConfigurationSet", req, &resp)
require.NoError(t, err)
require.Nil(t, resp)

roots = structs.IndexedCARoots{}
err = msgpackrpc.CallWithCodec(codec, "ConnectCA.Roots", &structs.DCSpecificRequest{}, &roots)
require.NoError(t, err)
require.Len(t, roots.Roots, 3)
active := roots.Active()
require.Len(t, active.IntermediateCerts, 2)

leafPEM := getLeafCert(t, codec, roots.TrustDomain, "dc1")
verifyLeafCert(t, roots.Active(), leafPEM)

// original certs from old root cert should still verify
verifyLeafCertWithRoots(t, roots, origLeaf)
})
}

// renewLeafSigningCert mimics RenewIntermediate in a secondary. This
Expand Down

0 comments on commit a802aab

Please sign in to comment.