27bb03bbc0
* adding copyright header * fix fmt and a test
125 lines
3.2 KiB
Go
125 lines
3.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package healthcheck
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
|
)
|
|
|
|
type TooManyCerts struct {
|
|
Enabled bool
|
|
UnsupportedVersion bool
|
|
|
|
CountCritical int
|
|
CountWarning int
|
|
|
|
CertCounts int
|
|
FetchIssue *PathFetch
|
|
}
|
|
|
|
func NewTooManyCertsCheck() Check {
|
|
return &TooManyCerts{}
|
|
}
|
|
|
|
func (h *TooManyCerts) Name() string {
|
|
return "too_many_certs"
|
|
}
|
|
|
|
func (h *TooManyCerts) IsEnabled() bool {
|
|
return h.Enabled
|
|
}
|
|
|
|
func (h *TooManyCerts) DefaultConfig() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"count_critical": 250000,
|
|
"count_warning": 50000,
|
|
}
|
|
}
|
|
|
|
func (h *TooManyCerts) LoadConfig(config map[string]interface{}) error {
|
|
value, err := parseutil.SafeParseIntRange(config["count_critical"], 1, 15000000)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing %v.count_critical: %w", h.Name(), err)
|
|
}
|
|
h.CountCritical = int(value)
|
|
|
|
value, err = parseutil.SafeParseIntRange(config["count_warning"], 1, 15000000)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing %v.count_warning: %w", h.Name(), err)
|
|
}
|
|
h.CountWarning = int(value)
|
|
|
|
h.Enabled, err = parseutil.ParseBool(config["enabled"])
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing %v.enabled: %w", h.Name(), err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *TooManyCerts) FetchResources(e *Executor) error {
|
|
exit, leavesRet, _, err := pkiFetchLeavesList(e, func() {
|
|
h.UnsupportedVersion = true
|
|
})
|
|
h.FetchIssue = leavesRet
|
|
|
|
if exit || err != nil {
|
|
return err
|
|
}
|
|
|
|
h.CertCounts = leavesRet.ParsedCache["count"].(int)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *TooManyCerts) Evaluate(e *Executor) (results []*Result, err error) {
|
|
if h.UnsupportedVersion {
|
|
// Shouldn't happen; /certs has been around forever.
|
|
ret := Result{
|
|
Status: ResultInvalidVersion,
|
|
Endpoint: "/{{mount}}/certs",
|
|
Message: "This health check requires Vault 1.11+ but an earlier version of Vault Server was contacted, preventing this health check from running.",
|
|
}
|
|
return []*Result{&ret}, nil
|
|
}
|
|
|
|
if h.FetchIssue != nil && h.FetchIssue.IsSecretPermissionsError() {
|
|
ret := Result{
|
|
Status: ResultInsufficientPermissions,
|
|
Endpoint: h.FetchIssue.Path,
|
|
Message: "Without this information, this health check is unable to function.",
|
|
}
|
|
|
|
if e.Client.Token() == "" {
|
|
ret.Message = "No token available so unable to list the endpoint for this mount. " + ret.Message
|
|
} else {
|
|
ret.Message = "This token lacks permission to list the endpoint for this mount. " + ret.Message
|
|
}
|
|
|
|
results = append(results, &ret)
|
|
return
|
|
}
|
|
|
|
ret := Result{
|
|
Status: ResultOK,
|
|
Endpoint: "/{{mount}}/certs",
|
|
Message: "This mount has an OK number of stored certificates.",
|
|
}
|
|
|
|
baseMsg := "This PKI mount has %v outstanding stored certificates; consider using no_store=false on roles, running tidy operations periodically, and using shorter certificate lifetimes to reduce the storage pressure on this mount."
|
|
if h.CertCounts >= h.CountCritical {
|
|
ret.Status = ResultCritical
|
|
ret.Message = fmt.Sprintf(baseMsg, h.CertCounts)
|
|
} else if h.CertCounts >= h.CountWarning {
|
|
ret.Status = ResultWarning
|
|
ret.Message = fmt.Sprintf(baseMsg, h.CertCounts)
|
|
}
|
|
|
|
results = append(results, &ret)
|
|
|
|
return
|
|
}
|