2023-03-15 16:00:52 +00:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2022-11-22 15:44:34 +00:00
package healthcheck
import (
"fmt"
"strings"
"github.com/hashicorp/go-secure-stdlib/parseutil"
)
type AllowIfModifiedSince struct {
Enabled bool
UnsupportedVersion bool
TuneData map [ string ] interface { }
2023-02-22 14:01:29 +00:00
Fetcher * PathFetch
2022-11-22 15:44:34 +00:00
}
func NewAllowIfModifiedSinceCheck ( ) Check {
return & AllowIfModifiedSince { }
}
func ( h * AllowIfModifiedSince ) Name ( ) string {
return "allow_if_modified_since"
}
func ( h * AllowIfModifiedSince ) IsEnabled ( ) bool {
return h . Enabled
}
func ( h * AllowIfModifiedSince ) DefaultConfig ( ) map [ string ] interface { } {
return map [ string ] interface { } { }
}
func ( h * AllowIfModifiedSince ) LoadConfig ( config map [ string ] interface { } ) error {
var err error
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 * AllowIfModifiedSince ) FetchResources ( e * Executor ) error {
2023-02-22 14:01:29 +00:00
var exit bool
var err error
exit , h . Fetcher , h . TuneData , err = fetchMountTune ( e , func ( ) {
2022-11-22 15:44:34 +00:00
h . UnsupportedVersion = true
} )
2023-02-22 14:01:29 +00:00
if exit || err != nil {
2022-11-22 15:44:34 +00:00
return err
}
return nil
}
func ( h * AllowIfModifiedSince ) Evaluate ( e * Executor ) ( results [ ] * Result , err error ) {
if h . UnsupportedVersion {
ret := Result {
Status : ResultInvalidVersion ,
Endpoint : "/sys/mounts/{{mount}}/tune" ,
2023-02-22 14:01:29 +00:00
Message : "This health check requires Vault 1.12+ but an earlier version of Vault Server was contacted, preventing this health check from running." ,
2022-11-22 15:44:34 +00:00
}
return [ ] * Result { & ret } , nil
}
2023-02-22 14:01:29 +00:00
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
}
2023-02-14 13:51:44 +00:00
req , err := StringList ( h . TuneData [ "passthrough_request_headers" ] )
2022-11-22 15:44:34 +00:00
if err != nil {
return nil , fmt . Errorf ( "unable to parse value from server for passthrough_request_headers: %w" , err )
}
2023-02-14 13:51:44 +00:00
resp , err := StringList ( h . TuneData [ "allowed_response_headers" ] )
2022-11-22 15:44:34 +00:00
if err != nil {
return nil , fmt . Errorf ( "unable to parse value from server for allowed_response_headers: %w" , err )
}
2023-02-22 14:01:29 +00:00
foundIMS := false
2022-11-22 15:44:34 +00:00
for _ , param := range req {
if strings . EqualFold ( param , "If-Modified-Since" ) {
foundIMS = true
break
}
}
2023-02-22 14:01:29 +00:00
foundLM := false
2022-11-22 15:44:34 +00:00
for _ , param := range resp {
if strings . EqualFold ( param , "Last-Modified" ) {
foundLM = true
break
}
}
if ! foundIMS || ! foundLM {
ret := Result {
Status : ResultInformational ,
Endpoint : "/sys/mounts/{{mount}}/tune" ,
Message : "Mount hasn't enabled If-Modified-Since Request or Last-Modified Response headers; consider enabling these headers to allow clients to fetch CAs and CRLs only when they've changed, reducing total bandwidth." ,
}
results = append ( results , & ret )
2022-11-23 14:42:19 +00:00
} else {
ret := Result {
Status : ResultOK ,
Endpoint : "/sys/mounts/{{mount}}/tune" ,
Message : "Mount allows the If-Modified-Since request header and Last-Modified response header." ,
}
results = append ( results , & ret )
2022-11-22 15:44:34 +00:00
}
return
}