27bb03bbc0
* adding copyright header * fix fmt and a test
198 lines
5.4 KiB
Go
198 lines
5.4 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package healthcheck
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
|
|
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
|
)
|
|
|
|
type EnableAutoTidy struct {
|
|
Enabled bool
|
|
UnsupportedVersion bool
|
|
|
|
IntervalDurationCritical time.Duration
|
|
IntervalDurationWarning time.Duration
|
|
PauseDurationCritical time.Duration
|
|
PauseDurationWarning time.Duration
|
|
|
|
TidyConfig *PathFetch
|
|
}
|
|
|
|
func NewEnableAutoTidyCheck() Check {
|
|
return &EnableAutoTidy{}
|
|
}
|
|
|
|
func (h *EnableAutoTidy) Name() string {
|
|
return "enable_auto_tidy"
|
|
}
|
|
|
|
func (h *EnableAutoTidy) IsEnabled() bool {
|
|
return h.Enabled
|
|
}
|
|
|
|
func (h *EnableAutoTidy) DefaultConfig() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"interval_duration_critical": "7d",
|
|
"interval_duration_warning": "2d",
|
|
"pause_duration_critical": "1s",
|
|
"pause_duration_warning": "200ms",
|
|
}
|
|
}
|
|
|
|
func (h *EnableAutoTidy) fromConfig(config map[string]interface{}, param string) (time.Duration, error) {
|
|
value, err := parseutil.ParseDurationSecond(config[param])
|
|
if err != nil {
|
|
return time.Duration(0), fmt.Errorf("failed to parse parameter %v.%v=%v: %w", h.Name(), param, config[param], err)
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func (h *EnableAutoTidy) LoadConfig(config map[string]interface{}) error {
|
|
var err error
|
|
|
|
h.IntervalDurationCritical, err = h.fromConfig(config, "interval_duration_critical")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h.IntervalDurationWarning, err = h.fromConfig(config, "interval_duration_warning")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h.PauseDurationCritical, err = h.fromConfig(config, "pause_duration_critical")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h.PauseDurationWarning, err = h.fromConfig(config, "pause_duration_warning")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
enabled, err := parseutil.ParseBool(config["enabled"])
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing %v.enabled: %w", h.Name(), err)
|
|
}
|
|
h.Enabled = enabled
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *EnableAutoTidy) FetchResources(e *Executor) error {
|
|
var err error
|
|
h.TidyConfig, err = e.FetchIfNotFetched(logical.ReadOperation, "/{{mount}}/config/auto-tidy")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if h.TidyConfig.IsUnsupportedPathError() {
|
|
h.UnsupportedVersion = true
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *EnableAutoTidy) Evaluate(e *Executor) (results []*Result, err error) {
|
|
if h.UnsupportedVersion {
|
|
ret := Result{
|
|
Status: ResultInvalidVersion,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: "This health check requires Vault 1.12+, but an earlier version of Vault Server was contacted, preventing this health check from running.",
|
|
}
|
|
return []*Result{&ret}, nil
|
|
}
|
|
|
|
if h.TidyConfig == nil {
|
|
return
|
|
}
|
|
|
|
if h.TidyConfig.IsSecretPermissionsError() {
|
|
ret := Result{
|
|
Status: ResultInsufficientPermissions,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: "This prevents the health check from functioning at all, as it cannot .",
|
|
}
|
|
|
|
if e.Client.Token() == "" {
|
|
ret.Message = "No token available so unable read authenticated auto-tidy configuration for this mount. " + ret.Message
|
|
} else {
|
|
ret.Message = "This token lacks permission to read the auto-tidy configuration for this mount. " + ret.Message
|
|
}
|
|
|
|
return []*Result{&ret}, nil
|
|
}
|
|
|
|
isEnabled := h.TidyConfig.Secret.Data["enabled"].(bool)
|
|
intervalDuration, err := parseutil.ParseDurationSecond(h.TidyConfig.Secret.Data["interval_duration"])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing API response from server for interval_duration: %w", err)
|
|
}
|
|
|
|
pauseDuration, err := parseutil.ParseDurationSecond(h.TidyConfig.Secret.Data["pause_duration"])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing API response from server for pause_duration: %w", err)
|
|
}
|
|
|
|
if !isEnabled {
|
|
ret := Result{
|
|
Status: ResultInformational,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: "Auto-tidy is currently disabled; consider enabling auto-tidy to execute tidy operations periodically. This helps the health and performance of a mount.",
|
|
}
|
|
results = append(results, &ret)
|
|
} else {
|
|
baseMsg := "Auto-tidy is configured with too long of a value for %v (%v); this could impact performance as tidies run too infrequently or take too long to execute."
|
|
|
|
if intervalDuration >= h.IntervalDurationCritical {
|
|
ret := Result{
|
|
Status: ResultCritical,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: fmt.Sprintf(baseMsg, "interval_duration", intervalDuration),
|
|
}
|
|
results = append(results, &ret)
|
|
} else if intervalDuration >= h.IntervalDurationWarning {
|
|
ret := Result{
|
|
Status: ResultWarning,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: fmt.Sprintf(baseMsg, "interval_duration", intervalDuration),
|
|
}
|
|
results = append(results, &ret)
|
|
}
|
|
|
|
if pauseDuration >= h.PauseDurationCritical {
|
|
ret := Result{
|
|
Status: ResultCritical,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: fmt.Sprintf(baseMsg, "pause_duration", pauseDuration),
|
|
}
|
|
results = append(results, &ret)
|
|
} else if pauseDuration >= h.PauseDurationWarning {
|
|
ret := Result{
|
|
Status: ResultWarning,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: fmt.Sprintf(baseMsg, "pause_duration", pauseDuration),
|
|
}
|
|
results = append(results, &ret)
|
|
}
|
|
|
|
if len(results) == 0 {
|
|
ret := Result{
|
|
Status: ResultOK,
|
|
Endpoint: "/{{mount}}/config/auto-tidy",
|
|
Message: "Auto-tidy is enabled and configured appropriately.",
|
|
}
|
|
results = append(results, &ret)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|