2016-09-01 18:02:19 +00:00
|
|
|
package fingerprint
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2018-09-16 00:48:59 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2018-01-24 14:09:53 +00:00
|
|
|
cstructs "github.com/hashicorp/nomad/client/structs"
|
2016-09-01 18:02:19 +00:00
|
|
|
vapi "github.com/hashicorp/vault/api"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
vaultAvailable = "available"
|
|
|
|
vaultUnavailable = "unavailable"
|
|
|
|
)
|
|
|
|
|
2016-09-01 20:38:31 +00:00
|
|
|
// VaultFingerprint is used to fingerprint for Vault
|
2016-09-01 18:02:19 +00:00
|
|
|
type VaultFingerprint struct {
|
2018-09-16 00:48:59 +00:00
|
|
|
logger log.Logger
|
2016-09-01 18:02:19 +00:00
|
|
|
client *vapi.Client
|
|
|
|
lastState string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewVaultFingerprint is used to create a Vault fingerprint
|
2018-09-16 00:48:59 +00:00
|
|
|
func NewVaultFingerprint(logger log.Logger) Fingerprint {
|
|
|
|
return &VaultFingerprint{logger: logger.Named("vault"), lastState: vaultUnavailable}
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
|
2018-01-24 14:09:53 +00:00
|
|
|
func (f *VaultFingerprint) Fingerprint(req *cstructs.FingerprintRequest, resp *cstructs.FingerprintResponse) error {
|
|
|
|
config := req.Config
|
|
|
|
|
2016-10-11 01:04:39 +00:00
|
|
|
if config.VaultConfig == nil || !config.VaultConfig.IsEnabled() {
|
2018-01-24 14:09:53 +00:00
|
|
|
return nil
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only create the client once to avoid creating too many connections to
|
|
|
|
// Vault.
|
|
|
|
if f.client == nil {
|
|
|
|
vaultConfig, err := config.VaultConfig.ApiConfig()
|
|
|
|
if err != nil {
|
2018-01-24 14:09:53 +00:00
|
|
|
return fmt.Errorf("Failed to initialize the Vault client config: %v", err)
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
f.client, err = vapi.NewClient(vaultConfig)
|
|
|
|
if err != nil {
|
2018-01-24 14:09:53 +00:00
|
|
|
return fmt.Errorf("Failed to initialize Vault client: %s", err)
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect to vault and parse its information
|
|
|
|
status, err := f.client.Sys().SealStatus()
|
|
|
|
if err != nil {
|
2018-01-26 19:31:37 +00:00
|
|
|
f.clearVaultAttributes(resp)
|
2016-09-01 18:02:19 +00:00
|
|
|
// Print a message indicating that Vault is not available anymore
|
|
|
|
if f.lastState == vaultAvailable {
|
2018-09-16 00:48:59 +00:00
|
|
|
f.logger.Info("Vault is unavailable")
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
f.lastState = vaultUnavailable
|
2018-01-24 14:09:53 +00:00
|
|
|
return nil
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 16:21:07 +00:00
|
|
|
resp.AddAttribute("vault.accessible", strconv.FormatBool(true))
|
2017-09-26 22:26:33 +00:00
|
|
|
// We strip the Vault prefix because < 0.6.2 the version looks like:
|
2016-09-01 18:02:19 +00:00
|
|
|
// status.Version = "Vault v0.6.1"
|
2018-01-26 16:21:07 +00:00
|
|
|
resp.AddAttribute("vault.version", strings.TrimPrefix(status.Version, "Vault "))
|
|
|
|
resp.AddAttribute("vault.cluster_id", status.ClusterID)
|
|
|
|
resp.AddAttribute("vault.cluster_name", status.ClusterName)
|
2016-09-01 18:02:19 +00:00
|
|
|
|
|
|
|
// If Vault was previously unavailable print a message to indicate the Agent
|
|
|
|
// is available now
|
|
|
|
if f.lastState == vaultUnavailable {
|
2018-09-16 00:48:59 +00:00
|
|
|
f.logger.Info("Vault is available")
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
f.lastState = vaultAvailable
|
2018-01-31 22:03:55 +00:00
|
|
|
resp.Detected = true
|
2018-01-24 14:09:53 +00:00
|
|
|
return nil
|
2016-09-01 18:02:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *VaultFingerprint) Periodic() (bool, time.Duration) {
|
|
|
|
return true, 15 * time.Second
|
|
|
|
}
|
2018-01-26 19:31:37 +00:00
|
|
|
|
|
|
|
func (f *VaultFingerprint) clearVaultAttributes(r *cstructs.FingerprintResponse) {
|
|
|
|
r.RemoveAttribute("vault.accessible")
|
|
|
|
r.RemoveAttribute("vault.version")
|
|
|
|
r.RemoveAttribute("vault.cluster_id")
|
|
|
|
r.RemoveAttribute("vault.cluster_name")
|
|
|
|
}
|