github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/fingerprint/vault.go (about) 1 package fingerprint 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "time" 8 9 log "github.com/hashicorp/go-hclog" 10 "github.com/hashicorp/nomad/helper" 11 vapi "github.com/hashicorp/vault/api" 12 ) 13 14 const ( 15 vaultAvailable = "available" 16 vaultUnavailable = "unavailable" 17 ) 18 19 // VaultFingerprint is used to fingerprint for Vault 20 type VaultFingerprint struct { 21 logger log.Logger 22 client *vapi.Client 23 lastState string 24 } 25 26 // NewVaultFingerprint is used to create a Vault fingerprint 27 func NewVaultFingerprint(logger log.Logger) Fingerprint { 28 return &VaultFingerprint{logger: logger.Named("vault"), lastState: vaultUnavailable} 29 } 30 31 func (f *VaultFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error { 32 config := req.Config 33 34 if config.VaultConfig == nil || !config.VaultConfig.IsEnabled() { 35 return nil 36 } 37 38 // Only create the client once to avoid creating too many connections to 39 // Vault. 40 if f.client == nil { 41 vaultConfig, err := config.VaultConfig.ApiConfig() 42 if err != nil { 43 return fmt.Errorf("Failed to initialize the Vault client config: %v", err) 44 } 45 46 f.client, err = vapi.NewClient(vaultConfig) 47 if err != nil { 48 return fmt.Errorf("Failed to initialize Vault client: %s", err) 49 } 50 } 51 52 // Connect to vault and parse its information 53 status, err := f.client.Sys().SealStatus() 54 if err != nil { 55 56 // Print a message indicating that Vault is not available anymore 57 if f.lastState == vaultAvailable { 58 f.logger.Info("Vault is unavailable") 59 } 60 f.lastState = vaultUnavailable 61 return nil 62 } 63 64 resp.AddAttribute("vault.accessible", strconv.FormatBool(true)) 65 // We strip the Vault prefix because < 0.6.2 the version looks like: 66 // status.Version = "Vault v0.6.1" 67 resp.AddAttribute("vault.version", strings.TrimPrefix(status.Version, "Vault ")) 68 resp.AddAttribute("vault.cluster_id", status.ClusterID) 69 resp.AddAttribute("vault.cluster_name", status.ClusterName) 70 71 // If Vault was previously unavailable print a message to indicate the Agent 72 // is available now 73 if f.lastState == vaultUnavailable { 74 f.logger.Info("Vault is available") 75 } 76 f.lastState = vaultAvailable 77 resp.Detected = true 78 return nil 79 } 80 81 func (f *VaultFingerprint) Periodic() (bool, time.Duration) { 82 if f.lastState == vaultAvailable { 83 // Fingerprint infrequently once Vault is initially discovered with wide 84 // jitter to avoid thundering herds of fingerprints against central Vault 85 // servers. 86 return true, (30 * time.Second) + helper.RandomStagger(90*time.Second) 87 } 88 return true, 15 * time.Second 89 }