Handle permission issue on pki health-check tune checkers (#19276)

* Handle permission issue on pki health-check tune checkers

 - Prior to this fix, if the end-user's Vault token did not have permission to the
   mount's tune api, we would return as if the tunable params had not been set.
 - Now check to see if we encountered a permission issue and report that back to
   the end-user like the other checks do.
This commit is contained in:
Steven Clark 2023-02-22 09:01:29 -05:00 committed by GitHub
parent 5b52184766
commit c40570c144
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 19 deletions

3
changelog/19276.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
cli/pki: Properly report permission issues within health-check mount tune checks
```

View File

@ -12,6 +12,7 @@ type AllowIfModifiedSince struct {
UnsupportedVersion bool
TuneData map[string]interface{}
Fetcher *PathFetch
}
func NewAllowIfModifiedSinceCheck() Check {
@ -42,15 +43,16 @@ func (h *AllowIfModifiedSince) LoadConfig(config map[string]interface{}) error {
}
func (h *AllowIfModifiedSince) FetchResources(e *Executor) error {
exit, _, data, err := fetchMountTune(e, func() {
var exit bool
var err error
exit, h.Fetcher, h.TuneData, err = fetchMountTune(e, func() {
h.UnsupportedVersion = true
})
if exit {
if exit || err != nil {
return err
}
h.TuneData = data
return nil
}
@ -59,11 +61,28 @@ func (h *AllowIfModifiedSince) Evaluate(e *Executor) (results []*Result, err err
ret := Result{
Status: ResultInvalidVersion,
Endpoint: "/sys/mounts/{{mount}}/tune",
Message: "This health check requires Vault 1.9+ but an earlier version of Vault Server was contacted, preventing this health check from running.",
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.Fetcher.IsSecretPermissionsError() {
ret := Result{
Status: ResultInsufficientPermissions,
Endpoint: "/sys/mounts/{{mount}}/tune",
Message: "Without this information, this health check is unable to function.",
}
if e.Client.Token() == "" {
ret.Message = "No token available so unable read the tune endpoint for this mount. " + ret.Message
} else {
ret.Message = "This token lacks permission to read the tune endpoint for this mount. " + ret.Message
}
results = append(results, &ret)
return
}
req, err := StringList(h.TuneData["passthrough_request_headers"])
if err != nil {
return nil, fmt.Errorf("unable to parse value from server for passthrough_request_headers: %w", err)
@ -74,7 +93,7 @@ func (h *AllowIfModifiedSince) Evaluate(e *Executor) (results []*Result, err err
return nil, fmt.Errorf("unable to parse value from server for allowed_response_headers: %w", err)
}
var foundIMS bool = false
foundIMS := false
for _, param := range req {
if strings.EqualFold(param, "If-Modified-Since") {
foundIMS = true
@ -82,7 +101,7 @@ func (h *AllowIfModifiedSince) Evaluate(e *Executor) (results []*Result, err err
}
}
var foundLM bool = false
foundLM := false
for _, param := range resp {
if strings.EqualFold(param, "Last-Modified") {
foundLM = true

View File

@ -58,6 +58,7 @@ type AuditVisibility struct {
IgnoredParameters map[string]bool
TuneData map[string]interface{}
Fetcher *PathFetch
}
func NewAuditVisibilityCheck() Check {
@ -100,29 +101,46 @@ func (h *AuditVisibility) LoadConfig(config map[string]interface{}) error {
}
func (h *AuditVisibility) FetchResources(e *Executor) error {
exit, _, data, err := fetchMountTune(e, func() {
var exit bool
var err error
exit, h.Fetcher, h.TuneData, err = fetchMountTune(e, func() {
h.UnsupportedVersion = true
})
if exit {
if exit || err != nil {
return err
}
h.TuneData = data
return nil
}
func (h *AuditVisibility) 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.",
Endpoint: "/sys/mounts/{{mount}}/tune",
Message: "This health check requires Vault 1.9+ but an earlier version of Vault Server was contacted, preventing this health check from running.",
}
return []*Result{&ret}, nil
}
if h.Fetcher.IsSecretPermissionsError() {
ret := Result{
Status: ResultInsufficientPermissions,
Endpoint: "/sys/mounts/{{mount}}/tune",
Message: "Without this information, this health check is unable to function.",
}
if e.Client.Token() == "" {
ret.Message = "No token available so unable read the tune endpoint for this mount. " + ret.Message
} else {
ret.Message = "This token lacks permission to read the tune endpoint for this mount. " + ret.Message
}
results = append(results, &ret)
return
}
sourceMap := map[string][]string{
"audit_non_hmac_request_keys": VisibleReqParams,
"audit_non_hmac_response_keys": VisibleRespParams,

View File

@ -93,7 +93,7 @@ func (h *TidyLastRun) Evaluate(e *Executor) (results []*Result, err error) {
ret := Result{
Status: ResultInsufficientPermissions,
Endpoint: "/{{mount}}/tidy-status",
Message: "Without this information, this health check is unable tof unction.",
Message: "Without this information, this health check is unable to function.",
}
if e.Client.Token() == "" {

View File

@ -35,7 +35,7 @@ func StringList(source interface{}) ([]string, error) {
func fetchMountTune(e *Executor, versionError func()) (bool, *PathFetch, map[string]interface{}, error) {
tuneRet, err := e.FetchIfNotFetched(logical.ReadOperation, "/sys/mounts/{{mount}}/tune")
if err != nil {
return true, nil, nil, err
return true, nil, nil, fmt.Errorf("failed to fetch mount tune information: %w", err)
}
if !tuneRet.IsSecretOK() {
@ -43,7 +43,7 @@ func fetchMountTune(e *Executor, versionError func()) (bool, *PathFetch, map[str
versionError()
}
return true, nil, nil, nil
return true, tuneRet, nil, nil
}
var data map[string]interface{} = nil