Update CI for leader renew CA test using Vault
This commit is contained in:
parent
62270c3f9a
commit
968fd8660d
|
@ -357,6 +357,8 @@ test-connect-ca-providers:
|
||||||
ifeq ("$(CIRCLECI)","true")
|
ifeq ("$(CIRCLECI)","true")
|
||||||
# Run in CI
|
# Run in CI
|
||||||
gotestsum --format=short-verbose --junitfile "$(TEST_RESULTS_DIR)/gotestsum-report.xml" -- -cover -coverprofile=coverage.txt ./agent/connect/ca
|
gotestsum --format=short-verbose --junitfile "$(TEST_RESULTS_DIR)/gotestsum-report.xml" -- -cover -coverprofile=coverage.txt ./agent/connect/ca
|
||||||
|
# Run leader tests that require Vault
|
||||||
|
gotestsum --format=short-verbose --junitfile "$(TEST_RESULTS_DIR)/gotestsum-report-leader.xml" -- -cover -coverprofile=coverage-leader.txt -run TestLeader_Vault_ ./agent/consul
|
||||||
else
|
else
|
||||||
# Run locally
|
# Run locally
|
||||||
@echo "Running /agent/connect/ca tests in verbose mode"
|
@echo "Running /agent/connect/ca tests in verbose mode"
|
||||||
|
|
|
@ -20,7 +20,7 @@ var ErrRateLimited = errors.New("operation rate limited by CA provider")
|
||||||
// intermediate cert in the primary datacenter as well as the secondary. This is used
|
// intermediate cert in the primary datacenter as well as the secondary. This is used
|
||||||
// when determining whether to run the intermediate renewal routine in the primary.
|
// when determining whether to run the intermediate renewal routine in the primary.
|
||||||
var PrimaryIntermediateProviders = map[string]struct{}{
|
var PrimaryIntermediateProviders = map[string]struct{}{
|
||||||
"vault": struct{}{},
|
"vault": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProviderConfig encapsulates all the data Consul passes to `Configure` on a
|
// ProviderConfig encapsulates all the data Consul passes to `Configure` on a
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error {
|
||||||
|
|
||||||
// Set up a renewer to renew the token automatically, if supported.
|
// Set up a renewer to renew the token automatically, if supported.
|
||||||
if token.Renewable {
|
if token.Renewable {
|
||||||
renewer, err := client.NewRenewer(&vaultapi.RenewerInput{
|
lifetimeWatcher, err := client.NewLifetimeWatcher(&vaultapi.LifetimeWatcherInput{
|
||||||
Secret: &vaultapi.Secret{
|
Secret: &vaultapi.Secret{
|
||||||
Auth: &vaultapi.SecretAuth{
|
Auth: &vaultapi.SecretAuth{
|
||||||
ClientToken: config.Token,
|
ClientToken: config.Token,
|
||||||
|
@ -102,6 +102,7 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Increment: token.TTL,
|
Increment: token.TTL,
|
||||||
|
RenewBehavior: vaultapi.RenewBehaviorIgnoreErrors,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error beginning Vault provider token renewal: %v", err)
|
return fmt.Errorf("Error beginning Vault provider token renewal: %v", err)
|
||||||
|
@ -109,31 +110,31 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error {
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
ctx, cancel := context.WithCancel(context.TODO())
|
||||||
v.shutdown = cancel
|
v.shutdown = cancel
|
||||||
go v.renewToken(ctx, renewer)
|
go v.renewToken(ctx, lifetimeWatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// renewToken uses a vaultapi.Renewer to repeatedly renew our token's lease.
|
// renewToken uses a vaultapi.Renewer to repeatedly renew our token's lease.
|
||||||
func (v *VaultProvider) renewToken(ctx context.Context, renewer *vaultapi.Renewer) {
|
func (v *VaultProvider) renewToken(ctx context.Context, watcher *vaultapi.LifetimeWatcher) {
|
||||||
go renewer.Renew()
|
go watcher.Start()
|
||||||
defer renewer.Stop()
|
defer watcher.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
|
|
||||||
case err := <-renewer.DoneCh():
|
case err := <-watcher.DoneCh():
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.logger.Error("Error renewing token for Vault provider", "error", err)
|
v.logger.Error("Error renewing token for Vault provider", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renewer routine has finished, so start it again.
|
// Watcher routine has finished, so start it again.
|
||||||
go renewer.Renew()
|
go watcher.Start()
|
||||||
|
|
||||||
case <-renewer.RenewCh():
|
case <-watcher.RenewCh():
|
||||||
v.logger.Error("Successfully renewed token for Vault provider")
|
v.logger.Error("Successfully renewed token for Vault provider")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -40,7 +38,7 @@ func TestVaultCAProvider_VaultTLSConfig(t *testing.T) {
|
||||||
func TestVaultCAProvider_SecondaryActiveIntermediate(t *testing.T) {
|
func TestVaultCAProvider_SecondaryActiveIntermediate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
provider, testVault := testVaultProviderWithConfig(t, false, nil)
|
provider, testVault := testVaultProviderWithConfig(t, false, nil)
|
||||||
defer testVault.Stop()
|
defer testVault.Stop()
|
||||||
|
@ -53,7 +51,7 @@ func TestVaultCAProvider_SecondaryActiveIntermediate(t *testing.T) {
|
||||||
|
|
||||||
func TestVaultCAProvider_RenewToken(t *testing.T) {
|
func TestVaultCAProvider_RenewToken(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
testVault, err := runTestVault(t)
|
testVault, err := runTestVault(t)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -90,7 +88,7 @@ func TestVaultCAProvider_RenewToken(t *testing.T) {
|
||||||
func TestVaultCAProvider_Bootstrap(t *testing.T) {
|
func TestVaultCAProvider_Bootstrap(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
provider, testVault := testVaultProvider(t)
|
provider, testVault := testVaultProvider(t)
|
||||||
defer testVault.Stop()
|
defer testVault.Stop()
|
||||||
|
@ -151,7 +149,7 @@ func assertCorrectKeyType(t *testing.T, want, certPEM string) {
|
||||||
func TestVaultCAProvider_SignLeaf(t *testing.T) {
|
func TestVaultCAProvider_SignLeaf(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
for _, tc := range KeyTestCases {
|
for _, tc := range KeyTestCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
@ -235,7 +233,7 @@ func TestVaultCAProvider_SignLeaf(t *testing.T) {
|
||||||
func TestVaultCAProvider_CrossSignCA(t *testing.T) {
|
func TestVaultCAProvider_CrossSignCA(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
tests := CASigningKeyTypeCases()
|
tests := CASigningKeyTypeCases()
|
||||||
|
|
||||||
|
@ -290,7 +288,7 @@ func TestVaultCAProvider_CrossSignCA(t *testing.T) {
|
||||||
func TestVaultProvider_SignIntermediate(t *testing.T) {
|
func TestVaultProvider_SignIntermediate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
tests := CASigningKeyTypeCases()
|
tests := CASigningKeyTypeCases()
|
||||||
|
|
||||||
|
@ -319,7 +317,7 @@ func TestVaultProvider_SignIntermediate(t *testing.T) {
|
||||||
func TestVaultProvider_SignIntermediateConsul(t *testing.T) {
|
func TestVaultProvider_SignIntermediateConsul(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
skipIfVaultNotPresent(t)
|
SkipIfVaultNotPresent(t)
|
||||||
|
|
||||||
// primary = Vault, secondary = Consul
|
// primary = Vault, secondary = Consul
|
||||||
t.Run("pri=vault,sec=consul", func(t *testing.T) {
|
t.Run("pri=vault,sec=consul", func(t *testing.T) {
|
||||||
|
@ -441,19 +439,3 @@ func createVaultProvider(t *testing.T, isPrimary bool, addr, token string, rawCo
|
||||||
|
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// skipIfVaultNotPresent skips the test if the vault binary is not in PATH.
|
|
||||||
//
|
|
||||||
// These tests may be skipped in CI. They are run as part of a separate
|
|
||||||
// integration test suite.
|
|
||||||
func skipIfVaultNotPresent(t *testing.T) {
|
|
||||||
vaultBinaryName := os.Getenv("VAULT_BINARY_NAME")
|
|
||||||
if vaultBinaryName == "" {
|
|
||||||
vaultBinaryName = "vault"
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := exec.LookPath(vaultBinaryName)
|
|
||||||
if err != nil || path == "" {
|
|
||||||
t.Skipf("%q not found on $PATH - download and install to run this test", vaultBinaryName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -83,6 +83,22 @@ func TestConsulProvider(t testing.T, d ConsulProviderStateDelegate) *ConsulProvi
|
||||||
return provider
|
return provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipIfVaultNotPresent skips the test if the vault binary is not in PATH.
|
||||||
|
//
|
||||||
|
// These tests may be skipped in CI. They are run as part of a separate
|
||||||
|
// integration test suite.
|
||||||
|
func SkipIfVaultNotPresent(t testing.T) {
|
||||||
|
vaultBinaryName := os.Getenv("VAULT_BINARY_NAME")
|
||||||
|
if vaultBinaryName == "" {
|
||||||
|
vaultBinaryName = "vault"
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := exec.LookPath(vaultBinaryName)
|
||||||
|
if err != nil || path == "" {
|
||||||
|
t.Skipf("%q not found on $PATH - download and install to run this test", vaultBinaryName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewTestVaultServer(t testing.T) *TestVaultServer {
|
func NewTestVaultServer(t testing.T) *TestVaultServer {
|
||||||
testVault, err := runTestVault(t)
|
testVault, err := runTestVault(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -180,7 +180,9 @@ func getCAProviderWithLock(s *Server) (ca.Provider, *structs.CARoot) {
|
||||||
return s.getCAProvider()
|
return s.getCAProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
|
func TestLeader_Vault_PrimaryCA_IntermediateRenew(t *testing.T) {
|
||||||
|
ca.SkipIfVaultNotPresent(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
|
||||||
|
@ -240,7 +242,7 @@ func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
|
||||||
provider, _ := getCAProviderWithLock(s1)
|
provider, _ := getCAProviderWithLock(s1)
|
||||||
intermediatePEM, err := provider.ActiveIntermediate()
|
intermediatePEM, err := provider.ActiveIntermediate()
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
cert, err := connect.ParseCert(intermediatePEM)
|
_, err = connect.ParseCert(intermediatePEM)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
// Wait for dc1's intermediate to be refreshed.
|
// Wait for dc1's intermediate to be refreshed.
|
||||||
|
@ -277,7 +279,7 @@ func TestLeader_PrimaryCA_IntermediateRenew(t *testing.T) {
|
||||||
leafPEM, err := provider.Sign(leafCsr)
|
leafPEM, err := provider.Sign(leafCsr)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
cert, err = connect.ParseCert(leafPEM)
|
cert, err := connect.ParseCert(leafPEM)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
// Check that the leaf signed by the new intermediate can be verified using the
|
// Check that the leaf signed by the new intermediate can be verified using the
|
||||||
|
|
Loading…
Reference in New Issue