Add a stop function to make sure the renewer is shut down on leader change

This commit is contained in:
Kyle Havlovitz 2020-09-10 06:12:48 -07:00
parent 411b6537ef
commit aa97366020
3 changed files with 38 additions and 6 deletions

View File

@ -164,3 +164,11 @@ type NeedsLogger interface {
// SetLogger will pass a configured Logger to the provider. // SetLogger will pass a configured Logger to the provider.
SetLogger(logger hclog.Logger) SetLogger(logger hclog.Logger)
} }
// NeedsStop is an optional interface that allows a CA to define a function
// to be called when the CA instance is no longer in use. This is different
// from Cleanup(), as only the local provider instance is being shut down
// such as in the case of a leader change.
type NeedsStop interface {
Stop()
}

View File

@ -9,6 +9,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
"sync"
"github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
@ -26,7 +27,10 @@ var ErrBackendNotInitialized = fmt.Errorf("backend not initialized")
type VaultProvider struct { type VaultProvider struct {
config *structs.VaultCAProviderConfig config *structs.VaultCAProviderConfig
client *vaultapi.Client client *vaultapi.Client
doneCh chan struct{}
shutdown bool
shutdownCh chan struct{}
shutdownLock sync.RWMutex
isPrimary bool isPrimary bool
clusterID string clusterID string
@ -71,7 +75,7 @@ func (v *VaultProvider) Configure(cfg ProviderConfig) error {
v.isPrimary = cfg.IsPrimary v.isPrimary = cfg.IsPrimary
v.clusterID = cfg.ClusterID v.clusterID = cfg.ClusterID
v.spiffeID = connect.SpiffeIDSigningForCluster(&structs.CAConfiguration{ClusterID: v.clusterID}) v.spiffeID = connect.SpiffeIDSigningForCluster(&structs.CAConfiguration{ClusterID: v.clusterID})
v.doneCh = make(chan struct{}, 0) v.shutdownCh = make(chan struct{}, 0)
// Look up the token to see if we can auto-renew its lease. // Look up the token to see if we can auto-renew its lease.
secret, err := client.Auth().Token().Lookup(config.Token) secret, err := client.Auth().Token().Lookup(config.Token)
@ -116,7 +120,7 @@ func (v *VaultProvider) renewToken(renewer *vaultapi.Renewer) {
for { for {
select { select {
case <-v.doneCh: case <-v.shutdownCh:
renewer.Stop() renewer.Stop()
return return
@ -501,13 +505,22 @@ func (c *VaultProvider) SupportsCrossSigning() (bool, error) {
// this down and recreate it on small config changes because the intermediate // this down and recreate it on small config changes because the intermediate
// certs get bundled with the leaf certs, so there's no cost to the CA changing. // certs get bundled with the leaf certs, so there's no cost to the CA changing.
func (v *VaultProvider) Cleanup() error { func (v *VaultProvider) Cleanup() error {
if v.doneCh != nil { v.Stop()
close(v.doneCh)
}
return v.client.Sys().Unmount(v.config.IntermediatePKIPath) return v.client.Sys().Unmount(v.config.IntermediatePKIPath)
} }
// Stop shuts down the token renew goroutine.
func (v *VaultProvider) Stop() {
v.shutdownLock.Lock()
defer v.shutdownLock.Unlock()
if !v.shutdown && v.shutdownCh != nil {
close(v.shutdownCh)
v.shutdown = true
}
}
func ParseVaultCAConfig(raw map[string]interface{}) (*structs.VaultCAProviderConfig, error) { func ParseVaultCAConfig(raw map[string]interface{}) (*structs.VaultCAProviderConfig, error) {
config := structs.VaultCAProviderConfig{ config := structs.VaultCAProviderConfig{
CommonCAProviderConfig: defaultCommonConfig(), CommonCAProviderConfig: defaultCommonConfig(),

View File

@ -567,6 +567,17 @@ func (s *Server) startConnectLeader() {
// stopConnectLeader stops connect specific leader functions. // stopConnectLeader stops connect specific leader functions.
func (s *Server) stopConnectLeader() { func (s *Server) stopConnectLeader() {
s.caProviderReconfigurationLock.Lock()
defer s.caProviderReconfigurationLock.Unlock()
// If the provider implements NeedsStop, we call Stop to perform any shutdown actions.
provider, _ := s.getCAProvider()
if provider != nil {
if needsStop, ok := provider.(ca.NeedsStop); ok {
needsStop.Stop()
}
}
s.leaderRoutineManager.Stop(secondaryCARootWatchRoutineName) s.leaderRoutineManager.Stop(secondaryCARootWatchRoutineName)
s.leaderRoutineManager.Stop(intentionReplicationRoutineName) s.leaderRoutineManager.Stop(intentionReplicationRoutineName)
s.leaderRoutineManager.Stop(caRootPruningRoutineName) s.leaderRoutineManager.Stop(caRootPruningRoutineName)