Skip to content

Commit

Permalink
Implement config parameter to allow unathenticated metricss access
Browse files Browse the repository at this point in the history
  • Loading branch information
michelvocks committed Oct 4, 2019
1 parent 338afe2 commit 8cc3cee
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 23 deletions.
58 changes: 39 additions & 19 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,22 @@ import (
"sync"
"time"

"golang.org/x/net/http/httpproxy"

"github.com/hashicorp/vault/helper/metricsutil"

monitoring "cloud.google.com/go/monitoring/apiv3"
metrics "github.com/armon/go-metrics"
"github.com/armon/go-metrics"
"github.com/armon/go-metrics/circonus"
"github.com/armon/go-metrics/datadog"
"github.com/armon/go-metrics/prometheus"
stackdriver "github.com/google/go-metrics-stackdriver"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
multierror "github.com/hashicorp/go-multierror"
sockaddr "github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/vault/audit"
"github.com/hashicorp/vault/command/server"
serverseal "github.com/hashicorp/vault/command/server/seal"
"github.com/hashicorp/vault/helper/builtinplugins"
gatedwriter "github.com/hashicorp/vault/helper/gated-writer"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/reload"
vaulthttp "github.com/hashicorp/vault/http"
Expand All @@ -54,8 +51,9 @@ import (
vaultseal "github.com/hashicorp/vault/vault/seal"
shamirseal "github.com/hashicorp/vault/vault/seal/shamir"
"github.com/mitchellh/cli"
testing "github.com/mitchellh/go-testing-interface"
"github.com/mitchellh/go-testing-interface"
"github.com/posener/complete"
"golang.org/x/net/http/httpproxy"
"google.golang.org/api/option"
"google.golang.org/grpc/grpclog"
)
Expand Down Expand Up @@ -125,9 +123,10 @@ type ServerCommand struct {

type ServerListener struct {
net.Listener
config map[string]interface{}
maxRequestSize int64
maxRequestDuration time.Duration
config map[string]interface{}
maxRequestSize int64
maxRequestDuration time.Duration
unauthenticatedMetricsAccess bool
}

func (c *ServerCommand) Synopsis() string {
Expand Down Expand Up @@ -988,11 +987,31 @@ CLUSTER_SYNTHESIS_COMPLETE:
}
props["max_request_duration"] = fmt.Sprintf("%s", maxRequestDuration.String())

var unauthenticatedMetricsAccess bool
if telemetryRaw, ok := lnConfig.Config["telemetry"]; ok {
telemetry, ok := telemetryRaw.([]map[string]interface{})
if !ok {
c.UI.Error(fmt.Sprintf("Could not parse telemetry sink value %v", telemetryRaw))
return 1
}

for _, item := range telemetry {
if valRaw, ok := item["unauthenticated_metrics_access"]; ok {
unauthenticatedMetricsAccess, err = parseutil.ParseBool(valRaw)
if err != nil {
c.UI.Error(fmt.Sprintf("Could not parse unauthenticated_metrics_access value %v", valRaw))
return 1
}
}
}
}

lns = append(lns, ServerListener{
Listener: ln,
config: lnConfig.Config,
maxRequestSize: maxRequestSize,
maxRequestDuration: maxRequestDuration,
Listener: ln,
config: lnConfig.Config,
maxRequestSize: maxRequestSize,
maxRequestDuration: maxRequestDuration,
unauthenticatedMetricsAccess: unauthenticatedMetricsAccess,
})

// Store the listener props for output later
Expand Down Expand Up @@ -1229,10 +1248,11 @@ CLUSTER_SYNTHESIS_COMPLETE:
// Initialize the HTTP servers
for _, ln := range lns {
handler := vaulthttp.Handler(&vault.HandlerProperties{
Core: core,
MaxRequestSize: ln.maxRequestSize,
MaxRequestDuration: ln.maxRequestDuration,
DisablePrintableCheck: config.DisablePrintableCheck,
Core: core,
MaxRequestSize: ln.maxRequestSize,
MaxRequestDuration: ln.maxRequestDuration,
DisablePrintableCheck: config.DisablePrintableCheck,
UnauthenticatedMetricsAccess: ln.unauthenticatedMetricsAccess,
})

// We perform validation on the config earlier, we can just cast here
Expand Down
29 changes: 29 additions & 0 deletions http/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/hashicorp/errwrap"
cleanhttp "github.com/hashicorp/go-cleanhttp"
sockaddr "github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
Expand Down Expand Up @@ -147,6 +148,11 @@ func Handler(props *vault.HandlerProperties) http.Handler {
mux.Handle("/", handleUIRedirect())
}

// Register metrics path without authentication if enabled
if props.UnauthenticatedMetricsAccess {
mux.Handle("/v1/sys/metrics", handleMetricsUnauth(core))
}

additionalRoutes(mux, core)

// Wrap the handler in another handler to trigger all help paths.
Expand Down Expand Up @@ -515,6 +521,29 @@ func parseRequest(core *vault.Core, r *http.Request, w http.ResponseWriter, out
return nil, err
}

func handleMetricsUnauth(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req := &logical.Request{Headers: r.Header}
format := r.Form.Get("format")
if format == "" {
format = metricsutil.FormatFromRequest(req)
}

// Define response
resp, err := core.MetricsHelper().ResponseForFormat(format)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}

// Manually unarchive the logical response and send back the information
w.WriteHeader(resp.Data[logical.HTTPStatusCode].(int))
w.Header().Set("Content-Type", resp.Data[logical.HTTPContentType].(string))
w.Write(resp.Data[logical.HTTPRawBody].([]byte))
})
}

// handleRequestForwarding determines whether to forward a request or not,
// falling back on the older behavior of redirecting the client
func handleRequestForwarding(core *vault.Core, handler http.Handler) http.Handler {
Expand Down
6 changes: 6 additions & 0 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -1979,6 +1979,12 @@ func (c *Core) SetLogLevel(level log.Level) {
}
}

// MetricsHelper returns the global metrics helper which allows external
// packages to access Vault's internal metrics.
func (c *Core) MetricsHelper() *metricsutil.MetricsHelper {
return c.metricsHelper
}

// BuiltinRegistry is an interface that allows the "vault" package to use
// the registry of builtin plugins without getting an import cycle. It
// also allows for mocking the registry easily.
Expand Down
9 changes: 5 additions & 4 deletions vault/request_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ var (
// HandlerProperties is used to seed configuration into a vaulthttp.Handler.
// It's in this package to avoid a circular dependency
type HandlerProperties struct {
Core *Core
MaxRequestSize int64
MaxRequestDuration time.Duration
DisablePrintableCheck bool
Core *Core
MaxRequestSize int64
MaxRequestDuration time.Duration
DisablePrintableCheck bool
UnauthenticatedMetricsAccess bool
}

// fetchEntityAndDerivedPolicies returns the entity object for the given entity
Expand Down

0 comments on commit 8cc3cee

Please sign in to comment.