Skip to content

Commit

Permalink
Missing cherry picks 1.3.1 (#8051)
Browse files Browse the repository at this point in the history
* Output human duration in TTL warnings (#7901)

* Add enable_hostname_label option to telementry stanza (#7902)

* store secret key and value as an object to fix copy/show secret bug (#7926)

* Add accept header check for prometheus mime type (#7958)

* Add accept header check for prometheus mime type

* Fix small header filter bug. Add test

* Fix S3 configurable path handling (#7966)

Also remove some incorrect skipping of the S3 test.

Fixes #7362

* Ui/fix demoting status menu (#7997)

* fix bug where users couldn't click on update primary

* don't show status menu items when cluster isSecondary since those links don't work

* show the mode of replication in the status menu

* do not show server header in status menu when the contents are empty

* show Disaster Recovery instead of 'DR'

* do not show http metrics in status menu unless user is authenticated

* fix typo so icons in status menu show

* Transit: error when restoring to a name that looks like a path (#7998)

* Add test to verify #7663

* Validate name in transit key restore to not be a path

* overwrite bulma bug that crashes safari (#8023)
  • Loading branch information
briankassouf committed Dec 18, 2019
1 parent 6e06873 commit 37660a0
Show file tree
Hide file tree
Showing 18 changed files with 247 additions and 80 deletions.
15 changes: 14 additions & 1 deletion builtin/logical/transit/path_restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package transit

import (
"context"
"errors"
"strings"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
Expand Down Expand Up @@ -42,8 +44,19 @@ func (b *backend) pathRestoreUpdate(ctx context.Context, req *logical.Request, d
return logical.ErrorResponse("'backup' must be supplied"), nil
}

return nil, b.lm.RestorePolicy(ctx, req.Storage, d.Get("name").(string), backupB64, force)
keyName := d.Get("name").(string)
// if a name is given, make sure it does not contain any slashes and look like
// a path
if keyName != "" {
if strings.Contains(keyName, "/") {
return nil, ErrInvalidKeyName
}
}

return nil, b.lm.RestorePolicy(ctx, req.Storage, keyName, backupB64, force)
}

const pathRestoreHelpSyn = `Restore the named key`
const pathRestoreHelpDesc = `This path is used to restore the named key.`

var ErrInvalidKeyName = errors.New("key names cannot be paths")
67 changes: 66 additions & 1 deletion builtin/logical/transit/path_restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func TestTransit_Restore(t *testing.T) {
Force *bool
// The error we expect, if any
ExpectedErr error

// RestoreName is used to restore the key to a differnt name
RestoreName string
}{
{
// key does not already exist
Expand All @@ -116,6 +119,33 @@ func TestTransit_Restore(t *testing.T) {
Name: "Restore-with-force-no-seed",
Force: boolPtr(true),
},
{
// key already exists, restore to new name
Name: "Restore-new-name",
Seed: true,
RestoreName: "new-key",
},
{
// key already exists, restore to bad path, should error
Name: "Restore-new-name-bad-path",
Seed: true,
RestoreName: "sub/path/new-key",
ExpectedErr: ErrInvalidKeyName,
},
{
// using force shouldn't matter if the restore key name is different
Name: "Restore-with-force-seed-new-name",
Seed: true,
Force: boolPtr(true),
RestoreName: "other-key",
},
{
// using force shouldn't matter if the restore key name is different
Name: "Restore-with-out-force-seed-new-name",
Seed: true,
Force: boolPtr(false),
RestoreName: "other-key",
},
{
// using force shouldn't matter if the key doesn't exist
Name: "Restore-force-false",
Expand Down Expand Up @@ -154,8 +184,13 @@ func TestTransit_Restore(t *testing.T) {
}
}

restorePath := "restore"
if tc.RestoreName != "" {
restorePath = fmt.Sprintf("%s/%s", restorePath, tc.RestoreName)
}

restoreReq := &logical.Request{
Path: "restore",
Path: restorePath,
Operation: logical.UpdateOperation,
Storage: s,
Data: map[string]interface{}{
Expand Down Expand Up @@ -184,12 +219,42 @@ func TestTransit_Restore(t *testing.T) {
}
}

readKeyName := keyName
if tc.RestoreName != "" {
readKeyName = tc.RestoreName
}

// read the key and make sure it's there
readReq := &logical.Request{
Path: "keys/" + readKeyName,
Operation: logical.ReadOperation,
Storage: s,
}

resp, err = b.HandleRequest(context.Background(), readReq)
if resp != nil && resp.IsError() {
t.Fatalf("resp: %#v\nerr: %v", resp, err)
}

if tc.ExpectedErr == nil && resp == nil {
t.Fatal("expected to find a key, but got none")
}

// cleanup / delete key after each run
keyReq.Operation = logical.DeleteOperation
resp, err = b.HandleRequest(context.Background(), keyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("resp: %#v\nerr: %v", resp, err)
}

// cleanup / delete restore key after each run, if it was created
if tc.RestoreName != "" && tc.ExpectedErr == nil {
readReq.Operation = logical.DeleteOperation
resp, err = b.HandleRequest(context.Background(), readReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("resp: %#v\nerr: %v", resp, err)
}
}
})
}
}
1 change: 1 addition & 0 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,7 @@ func (c *ServerCommand) setupTelemetry(config *server.Config) (*metricsutil.Metr

metricsConf := metrics.DefaultConfig("vault")
metricsConf.EnableHostname = !telConfig.DisableHostname
metricsConf.EnableHostnameLabel = telConfig.EnableHostnameLabel

// Configure the statsite sink
var fanout metrics.FanoutSink
Expand Down
3 changes: 2 additions & 1 deletion command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ type Telemetry struct {
StatsiteAddr string `hcl:"statsite_address"`
StatsdAddr string `hcl:"statsd_address"`

DisableHostname bool `hcl:"disable_hostname"`
DisableHostname bool `hcl:"disable_hostname"`
EnableHostnameLabel bool `hcl:"enable_hostname_label"`

// Circonus: see https://github.com/circonus-labs/circonus-gometrics
// for more details on the various configuration options.
Expand Down
11 changes: 10 additions & 1 deletion helper/metricsutil/metricsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
const (
OpenMetricsMIMEType = "application/openmetrics-text"

PrometheusSchemaMIMEType = "prometheus/telemetry"

// ErrorContentType is the content type returned by an error response.
ErrorContentType = "text/plain"
)
Expand All @@ -38,7 +40,14 @@ func FormatFromRequest(req *logical.Request) string {
if len(acceptHeaders) > 0 {
acceptHeader := acceptHeaders[0]
if strings.HasPrefix(acceptHeader, OpenMetricsMIMEType) {
return "prometheus"
return PrometheusMetricFormat
}

// Look for prometheus accept header
for _, header := range acceptHeaders {
if strings.Contains(header, PrometheusSchemaMIMEType) {
return PrometheusMetricFormat
}
}
}
return ""
Expand Down
45 changes: 45 additions & 0 deletions helper/metricsutil/metricsutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package metricsutil

import (
"github.com/hashicorp/vault/sdk/logical"
"testing"
)

func TestFormatFromRequest(t *testing.T) {
testCases := []struct {
original *logical.Request
expected string
}{
{
original: &logical.Request{Headers: map[string][]string{
"Accept": {
"application/vnd.google.protobuf",
"schema=\"prometheus/telemetry\"",
},
}},
expected: "prometheus",
},
{
original: &logical.Request{Headers: map[string][]string{
"Accept": {
"schema=\"prometheus\"",
},
}},
expected: "",
},
{
original: &logical.Request{Headers: map[string][]string{
"Accept": {
"application/openmetrics-text",
},
}},
expected: "prometheus",
},
}

for _, tCase := range testCases {
if metricsType := FormatFromRequest(tCase.original); metricsType != tCase.expected {
t.Fatalf("expected %s but got %s", tCase.expected, metricsType)
}
}
}
9 changes: 7 additions & 2 deletions physical/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ func (s *S3Backend) Get(ctx context.Context, key string) (*physical.Entry, error
return nil, err
}

// Strip path prefix
if s.path != "" {
key = strings.TrimPrefix(key, s.path+"/")
}

ent := &physical.Entry{
Key: key,
Value: data.Bytes(),
Expand Down Expand Up @@ -266,8 +271,8 @@ func (s *S3Backend) List(ctx context.Context, prefix string) ([]string, error) {
// Setup prefix
prefix = path.Join(s.path, prefix)

// Validate prefix is ending with a "/"
if !strings.HasSuffix(prefix, "/") {
// Validate prefix (if present) is ending with a "/"
if prefix != "" && !strings.HasSuffix(prefix, "/") {
prefix += "/"
}

Expand Down
4 changes: 2 additions & 2 deletions physical/s3/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ func DoS3BackendTest(t *testing.T, kmsKeyId string) {

credsChain, err := credsConfig.GenerateCredentialChain()
if err != nil {
t.SkipNow()
t.Fatal(err)
}

_, err = credsChain.Get()
if err != nil {
t.SkipNow()
t.Fatal(err)
}

// If the variable is empty or doesn't exist, the default
Expand Down
23 changes: 21 additions & 2 deletions sdk/framework/lease.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package framework
import (
"context"
"fmt"
"strings"
"time"

"github.com/hashicorp/vault/sdk/logical"
Expand Down Expand Up @@ -61,7 +62,8 @@ func CalculateTTL(sysView logical.SystemView, increment, backendTTL, period, bac
// Cap the period value to the sys max_ttl value
if period > maxTTL {
warnings = append(warnings,
fmt.Sprintf("period of %q exceeded the effective max_ttl of %q; period value is capped accordingly", period, maxTTL))
fmt.Sprintf("period of %q exceeded the effective max_ttl of %q; period value is capped accordingly",
humanDuration(period), humanDuration(maxTTL)))
period = maxTTL
}
ttl = period
Expand Down Expand Up @@ -97,10 +99,27 @@ func CalculateTTL(sysView logical.SystemView, increment, backendTTL, period, bac
// cap the increment to whatever is left
if maxValidTTL-ttl < 0 {
warnings = append(warnings,
fmt.Sprintf("TTL of %q exceeded the effective max_ttl of %q; TTL value is capped accordingly", ttl, maxValidTTL))
fmt.Sprintf("TTL of %q exceeded the effective max_ttl of %q; TTL value is capped accordingly",
humanDuration(ttl), humanDuration(maxValidTTL)))
ttl = maxValidTTL
}
}

return ttl, warnings, nil
}

// humanDuration prints the time duration without zero elements.
func humanDuration(d time.Duration) string {
if d == 0 {
return "0s"
}

s := d.String()
if strings.HasSuffix(s, "m0s") {
s = s[:len(s)-2]
}
if idx := strings.Index(s, "h0m"); idx > 0 {
s = s[:idx+1] + s[idx+3:]
}
return s
}
2 changes: 1 addition & 1 deletion ui/app/models/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default DS.Model.extend({
}),

stateGlyph(state) {
const glyph = 'check-circled-outline';
const glyph = 'check-circle-outline';

const glyphs = {
'stream-wals': 'android-sync',
Expand Down
6 changes: 6 additions & 0 deletions ui/app/models/secret.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export default DS.Model.extend(KeyMixin, {
renewable: attr('boolean'),

secretData: attr('object'),
secretKeyAndValue: computed('secretData', function() {
const data = this.get('secretData');
return Object.keys(data).map(key => {
return { key, value: data[key] };
});
}),

dataAsJSONString: computed('secretData', function() {
return JSON.stringify(this.get('secretData'), null, 2);
Expand Down
4 changes: 0 additions & 4 deletions ui/app/styles/components/popup-menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@

.menu {
padding: $size-11 0;

small code {
margin-left: $spacing-xs;
}
}

button.link,
Expand Down
1 change: 1 addition & 0 deletions ui/app/styles/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import './core/navbar';
@import './core/notification';
@import './core/progress';
@import './core/select';
@import './core/switch';
@import './core/tables';
@import './core/tags';
Expand Down
3 changes: 3 additions & 0 deletions ui/app/styles/core/select.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.select select {
text-rendering: auto !important;
}
8 changes: 4 additions & 4 deletions ui/app/templates/partials/secret-form-show.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@
</div>
</div>
</div>
{{#each-in modelForData.secretData as |key value|}}
{{#info-table-row label=key value=value alwaysRender=true}}
{{masked-input value=value displayOnly=true allowCopy=true}}
{{#each modelForData.secretKeyAndValue as |secret|}}
{{#info-table-row label=secret.key value=secret.value alwaysRender=true}}
{{masked-input value=secret.value displayOnly=true allowCopy=true}}
{{/info-table-row}}
{{/each-in}}
{{/each}}
{{/if}}
{{/if}}
Loading

0 comments on commit 37660a0

Please sign in to comment.