Skip to content

Commit

Permalink
Merge branch 'configutil' into encryptedconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
jefferai committed May 14, 2020
2 parents ea2a7f3 + f047883 commit e1a5311
Show file tree
Hide file tree
Showing 44 changed files with 582 additions and 1,878 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ CHANGES:
* plugin: Add SDK method, `Sys.ReloadPlugin`, and CLI command, `vault plugin reload`,
for reloading plugins. [[GH-8777](https://github.com/hashicorp/vault/pull/8777)]
* sentinel: Add a sentinel config section, and "additional_enabled_modules", a list of Sentinel modules that may be imported in addition to the defaults.
* cubbyhole: Reject reads and writes to an empty ("") path. [[GH-8971](https://github.com/hashicorp/vault/pull/8971)]

IMPROVEMENTS:

Expand Down Expand Up @@ -174,6 +175,7 @@ BUG FIXES:
* identity: Fix incorrect caching of identity token JWKS responses [[GH-8412](https://github.com/hashicorp/vault/pull/8412)]
* metrics/stackdriver: Fix issue that prevents the stackdriver metrics library to create unnecessary stackdriver descriptors [[GH-8073](https://github.com/hashicorp/vault/pull/8073)]
* replication: Fix issue causing cubbyholes in namespaces on performance secondaries to not work.
* replication (enterprise): Unmounting a dynamic secrets backend could sometimes lead to replication errors. Change the order of operations to prevent that.
* seal (enterprise): Fix seal migration when transactional seal wrap backend is in use.
* secrets/database/influxdb: Fix potential panic if connection to the InfluxDB database cannot be established [[GH-8282](https://github.com/hashicorp/vault/pull/8282)]
* secrets/database/mysql: Ensures default static credential rotation statements are used [[GH-8240](https://github.com/hashicorp/vault/pull/8240)]
Expand Down
1 change: 0 additions & 1 deletion builtin/credential/okta/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

"github.com/hashicorp/go-cleanhttp"

oktaold "github.com/chrismalek/oktasdk-go/okta"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/tokenutil"
Expand Down
7 changes: 5 additions & 2 deletions builtin/logical/pki/path_config_ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ func (b *backend) pathCAWrite(ctx context.Context, req *logical.Request, data *f
}
}

if parsedBundle.PrivateKey == nil ||
parsedBundle.PrivateKeyType == certutil.UnknownPrivateKey {
if parsedBundle.PrivateKey == nil {
return logical.ErrorResponse("private key not found in the PEM bundle"), nil
}

if parsedBundle.PrivateKeyType == certutil.UnknownPrivateKey {
return logical.ErrorResponse("unknown private key found in the PEM bundle"), nil
}

if parsedBundle.Certificate == nil {
return logical.ErrorResponse("no certificate found in the PEM bundle"), nil
}
Expand Down
2 changes: 1 addition & 1 deletion command/agent/cache/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func StartListener(lnConfig *configutil.Listener) (net.Listener, *tls.Config, er
}

props := map[string]string{"addr": ln.Addr().String()}
tlsConf, _, err := listenerutil.GetTLSConfig(ln, lnConfig, props, nil)
tlsConf, _, err := listenerutil.TLSConfig(lnConfig, props, nil)
if err != nil {
return nil, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion command/seal_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ func testSealMigrationTransitToShamir(t *testing.T, setup teststorage.ClusterSet
// Create a Shamir seal.
logger := cluster.Logger.Named("shamir")
shamirSeal := vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewWrapper(&wrapping.WrapperOptions{
Wrapper: aeadwrapper.NewShamirWrapper(&wrapping.WrapperOptions{
Logger: logger,
}),
})
Expand Down
25 changes: 18 additions & 7 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,13 +554,16 @@ func (c *ServerCommand) runRecoveryMode() int {
sealType = configSeal.Type
}

infoKeys = append(infoKeys, "Seal Type")
info["Seal Type"] = sealType

var seal vault.Seal
defaultSeal := vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(&wrapping.WrapperOptions{
Logger: c.logger.Named("shamir"),
}),
})
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal-%s", sealType))
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal.%s", sealType))
wrapper, sealConfigError = configutil.ConfigureWrapper(configSeal, &infoKeys, &info, sealLogger)
if sealConfigError != nil {
if !errwrap.ContainsType(sealConfigError, new(logical.KeyNotFoundError)) {
Expand All @@ -576,9 +579,6 @@ func (c *ServerCommand) runRecoveryMode() int {
Wrapper: wrapper,
})
}
infoKeys = append(infoKeys, "Seal Type")
info["Seal Type"] = configSeal.Type

barrierSeal = seal

// Ensure that the seal finalizer is called, even if using verify-only
Expand Down Expand Up @@ -965,7 +965,14 @@ func (c *ServerCommand) Run(args []string) int {
"in a Docker container, provide the IPC_LOCK cap to the container."))
}

inmemMetrics, prometheusEnabled, err := configutil.SetupTelemetry(config.Telemetry, c.UI, "vault", "Vault", useragent.String())
inmemMetrics, metricSink, prometheusEnabled, err := configutil.SetupTelemetry(&configutil.SetupTelemetryOpts{
Config: config.Telemetry,
Ui: c.UI,
ServiceName: "vault",
DisplayName: "Vault",
UserAgent: useragent.String(),
ClusterName: config.ClusterName,
})
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing telemetry: %s", err))
return 1
Expand Down Expand Up @@ -1093,7 +1100,7 @@ func (c *ServerCommand) Run(args []string) int {
}

var seal vault.Seal
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal-%s", sealType))
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal.%s", sealType))
allLoggers = append(allLoggers, sealLogger)
defaultSeal := vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(&wrapping.WrapperOptions{
Expand Down Expand Up @@ -1174,6 +1181,7 @@ func (c *ServerCommand) Run(args []string) int {
BuiltinRegistry: builtinplugins.Registry,
DisableKeyEncodingChecks: config.DisablePrintableCheck,
MetricsHelper: metricsHelper,
MetricSink: metricSink,
SecureRandomReader: secureRandomReader,
}
if c.flagDev {
Expand Down Expand Up @@ -1705,14 +1713,17 @@ CLUSTER_SYNTHESIS_COMPLETE:

// Initialize the HTTP servers
for _, ln := range lns {
if ln.Config == nil {
c.UI.Error("Found nil listener config after parsing")
return 1
}
handler := vaulthttp.Handler(&vault.HandlerProperties{
Core: core,
ListenerConfig: ln.Config,
DisablePrintableCheck: config.DisablePrintableCheck,
RecoveryMode: c.flagRecovery,
})

// We perform validation on the config earlier, we can just cast here
if len(ln.Config.XForwardedForAuthorizedAddrs) > 0 {
handler = vaulthttp.WrapForwardedForHandler(handler, ln.Config)
}
Expand Down
17 changes: 14 additions & 3 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (

// Config is the configuration for the vault server.
type Config struct {
entConfig

*configutil.SharedConfig `hcl:"-"`

Storage *Storage `hcl:"-"`
Expand Down Expand Up @@ -291,9 +293,13 @@ func CheckConfig(c *Config, e error) (*Config, error) {
nonConfigSeals = append(nonConfigSeals, kms)
}

if len(nonConfigSeals) == 2 &&
(nonConfigSeals[0].Disabled && nonConfigSeals[1].Disabled || !nonConfigSeals[0].Disabled && !nonConfigSeals[1].Disabled) {
return nil, errors.New("seals: two seals provided but both are disabled or neither are disabled")
if len(nonConfigSeals) == 2 {
switch {
case nonConfigSeals[0].Disabled && nonConfigSeals[1].Disabled:
return nil, errors.New("seals: two seals provided but both are disabled")
case !nonConfigSeals[0].Disabled && !nonConfigSeals[1].Disabled:
return nil, errors.New("seals: two seals provided but neither is disabled")
}
}

return c, nil
Expand Down Expand Up @@ -447,6 +453,11 @@ func ParseConfig(d string) (*Config, error) {
}
}

entConfig := &(result.entConfig)
if err := entConfig.parseConfig(list); err != nil {
return nil, errwrap.Wrapf("error parsing enterprise config: {{err}}", err)
}

return result, nil
}

Expand Down
14 changes: 14 additions & 0 deletions command/server/config_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// +build !enterprise

package server

import (
"github.com/hashicorp/hcl/hcl/ast"
)

type entConfig struct {
}

func (ec *entConfig) parseConfig(list *ast.ObjectList) error {
return nil
}
2 changes: 1 addition & 1 deletion command/server/listener_tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func tcpListenerFactory(l *configutil.Listener, _ io.Writer, ui cli.Ui) (net.Lis
}
}

tlsConfig, reloadFunc, err := listenerutil.GetTLSConfig(ln, l, props, ui)
tlsConfig, reloadFunc, err := listenerutil.TLSConfig(l, props, ui)
if err != nil {
return nil, nil, nil, err
}
Expand Down
59 changes: 59 additions & 0 deletions helper/metricsutil/wrapped_metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package metricsutil

import (
"time"

metrics "github.com/armon/go-metrics"
)

// ClusterMetricSink serves as a shim around go-metrics
// and inserts a "cluster" label.
//
// It also provides a mechanism to limit the cardinality of the labels on a gauge
// (at each reporting interval, which isn't sufficient if there is variability in which
// labels are the top N) and a backoff mechanism for gauge computation.
type ClusterMetricSink struct {
// ClusterName is either the cluster ID, or a name provided
// in the telemetry configuration stanza.
ClusterName string

MaxGaugeCardinality int
GaugeInterval time.Duration

// Sink is the go-metrics sink to send to
Sink metrics.MetricSink
}

// Convenience alias
type Label = metrics.Label

func (m *ClusterMetricSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
m.Sink.SetGaugeWithLabels(key, val,
append(labels, Label{"cluster", m.ClusterName}))
}

func (m *ClusterMetricSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
m.Sink.IncrCounterWithLabels(key, val,
append(labels, Label{"cluster", m.ClusterName}))
}

func (m *ClusterMetricSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
m.Sink.AddSampleWithLabels(key, val,
append(labels, Label{"cluster", m.ClusterName}))
}

// BlackholeSink is a default suitable for use in unit tests.
func BlackholeSink() *ClusterMetricSink {
return &ClusterMetricSink{
ClusterName: "",
Sink: &metrics.BlackholeSink{},
}
}

// SetDefaultClusterName changes the cluster name from its default value,
// if it has not previously been configured.
func (m *ClusterMetricSink) SetDefaultClusterName(clusterName string) {
if m.ClusterName == "" {
m.ClusterName = clusterName
}
}
102 changes: 102 additions & 0 deletions helper/metricsutil/wrapped_metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package metricsutil

import (
"testing"
"time"

"github.com/armon/go-metrics"
)

func isLabelPresent(toFind Label, ls []Label) bool {
for _, l := range ls {
if l == toFind {
return true
}
}
return false
}

func TestClusterLabelPresent(t *testing.T) {
testClusterName := "test-cluster"

// Use a ridiculously long time to minimize the chance
// that we have to deal with more than one interval.
// InMemSink rounds down to an interval boundary rather than
// starting one at the time of initialization.
inmemSink := metrics.NewInmemSink(
1000000*time.Hour,
2000000*time.Hour)
clusterSink := &ClusterMetricSink{
ClusterName: testClusterName,
Sink: inmemSink,
}

key1 := []string{"aaa", "bbb"}
key2 := []string{"ccc", "ddd"}
key3 := []string{"eee", "fff"}
labels1 := []Label{{"dim1", "val1"}}
labels2 := []Label{{"dim2", "val2"}}
labels3 := []Label{{"dim3", "val3"}}
clusterLabel := Label{"cluster", testClusterName}
expectedKey1 := "aaa.bbb;dim1=val1;cluster=" + testClusterName
expectedKey2 := "ccc.ddd;dim2=val2;cluster=" + testClusterName
expectedKey3 := "eee.fff;dim3=val3;cluster=" + testClusterName

clusterSink.SetGaugeWithLabels(key1, 1.0, labels1)
clusterSink.IncrCounterWithLabels(key2, 2.0, labels2)
clusterSink.AddSampleWithLabels(key3, 3.0, labels3)

intervals := inmemSink.Data()
// If we start very close to the end of an interval, then our metrics might be
// split across two different buckets. We won't write the code to try to handle that.
// 100000-hours = at most once every 4167 days
if len(intervals) > 1 {
t.Skip("Detected interval crossing.")
}

// Check Gauge
g, ok := intervals[0].Gauges[expectedKey1]
if !ok {
t.Fatal("Key", expectedKey1, "not found in map", intervals[0].Gauges)
}
if g.Value != 1.0 {
t.Error("Gauge value", g.Value, "does not match", 1.0)
}
if !isLabelPresent(labels1[0], g.Labels) {
t.Error("Gauge label", g.Labels, "does not include", labels1)
}
if !isLabelPresent(clusterLabel, g.Labels) {
t.Error("Gauge label", g.Labels, "does not include", clusterLabel)
}

// Check Counter
c, ok := intervals[0].Counters[expectedKey2]
if !ok {
t.Fatal("Key", expectedKey2, "not found in map", intervals[0].Counters)
}
if c.Sum != 2.0 {
t.Error("Counter value", c.Sum, "does not match", 2.0)
}
if !isLabelPresent(labels2[0], c.Labels) {
t.Error("Counter label", c.Labels, "does not include", labels2)
}
if !isLabelPresent(clusterLabel, c.Labels) {
t.Error("Counter label", c.Labels, "does not include", clusterLabel)
}

// Check Sample
s, ok := intervals[0].Samples[expectedKey3]
if !ok {
t.Fatal("Key", expectedKey3, "not found in map", intervals[0].Samples)
}
if s.Sum != 3.0 {
t.Error("Sample value", s.Sum, "does not match", 3.0)
}
if !isLabelPresent(labels3[0], s.Labels) {
t.Error("Sample label", s.Labels, "does not include", labels3)
}
if !isLabelPresent(clusterLabel, s.Labels) {
t.Error("Sample label", s.Labels, "does not include", clusterLabel)
}

}

0 comments on commit e1a5311

Please sign in to comment.