oss changes for entropy augmentation feature (#7670)

* oss changes for entropy augmentation feature

* fix oss command/server/config tests

* update go.sum

* fix logical_system and http/ tests

* adds vendored files

* removes unused variable
This commit is contained in:
Lexman
2019-10-17 10:33:00 -07:00
committed by GitHub
parent 9a3369c566
commit 47a54ac8bc
82 changed files with 1347 additions and 729 deletions

View File

@@ -38,6 +38,7 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=

View File

@@ -134,6 +134,7 @@ type MountInput struct {
Config MountConfigInput `json:"config"`
Local bool `json:"local"`
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
Options map[string]string `json:"options"`
// Deprecated: Newer server responses should be returning this information in the
@@ -167,6 +168,7 @@ type MountOutput struct {
Options map[string]string `json:"options"`
Local bool `json:"local"`
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
}
type MountConfigOutput struct {

View File

@@ -333,6 +333,7 @@ func (b *backend) pathKeyCreate(ctx context.Context, req *logical.Request, data
Digits: keyDigits,
Algorithm: keyAlgorithm,
SecretSize: uintKeySize,
Rand: b.GetRandomReader(),
})
if err != nil {
return logical.ErrorResponse("an error occurred while generating a key"), err

View File

@@ -2,6 +2,7 @@ package transit
import (
"context"
cryptoRand "crypto/rand"
"encoding/base64"
"fmt"
"math/rand"
@@ -922,7 +923,7 @@ func testDerivedKeyUpgrade(t *testing.T, keyType keysutil.KeyType) {
}
p.MigrateKeyToKeysMap()
p.Upgrade(context.Background(), storage) // Need to run the upgrade code to make the migration stick
p.Upgrade(context.Background(), storage, cryptoRand.Reader) // Need to run the upgrade code to make the migration stick
if p.KDF != keysutil.Kdf_hmac_sha256_counter {
t.Fatalf("bad KDF value by default; counter val is %d, KDF val is %d, policy is %#v", keysutil.Kdf_hmac_sha256_counter, p.KDF, *p)

View File

@@ -65,7 +65,7 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -102,7 +102,7 @@ func (b *backend) pathDatakeyWrite(ctx context.Context, req *logical.Request, d
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -115,7 +115,7 @@ func (b *backend) pathDecryptWrite(ctx context.Context, req *logical.Request, d
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: d.Get("name").(string),
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -129,7 +129,7 @@ func (b *backend) pathEncryptExistenceCheck(ctx context.Context, req *logical.Re
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return false, err
}
@@ -244,7 +244,7 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
Name: name,
}
}
p, upserted, err = b.lm.GetPolicy(ctx, polReq)
p, upserted, err = b.lm.GetPolicy(ctx, polReq, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -67,7 +67,7 @@ func (b *backend) pathPolicyExportRead(ctx context.Context, req *logical.Request
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -100,7 +100,7 @@ func (b *backend) pathHMACWrite(ctx context.Context, req *logical.Request, d *fr
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}
@@ -229,7 +229,7 @@ func (b *backend) pathHMACVerify(ctx context.Context, req *logical.Request, d *f
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -29,7 +29,7 @@ func TestTransit_HMAC(t *testing.T) {
p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "foo",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -123,7 +123,7 @@ func TestTransit_HMAC(t *testing.T) {
req.Data["input"] = "dGhlIHF1aWNrIGJyb3duIGZveA=="
// Rotate
err = p.Rotate(context.Background(), storage)
err = p.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -199,7 +199,7 @@ func TestTransit_batchHMAC(t *testing.T) {
p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "foo",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -297,7 +297,7 @@ func TestTransit_batchHMAC(t *testing.T) {
}
// Rotate
err = p.Rotate(context.Background(), storage)
err = p.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}

View File

@@ -161,7 +161,7 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest
}
p, upserted, err := b.lm.GetPolicy(ctx, polReq)
p, upserted, err := b.lm.GetPolicy(ctx, polReq, b.GetRandomReader())
if err != nil {
return nil, err
}
@@ -193,7 +193,7 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -118,7 +118,7 @@ func (b *backend) pathRewrapWrite(ctx context.Context, req *logical.Request, d *
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: d.Get("name").(string),
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -34,7 +34,7 @@ func (b *backend) pathRotateWrite(ctx context.Context, req *logical.Request, d *
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}
@@ -46,7 +46,7 @@ func (b *backend) pathRotateWrite(ctx context.Context, req *logical.Request, d *
}
// Rotate the policy
err = p.Rotate(ctx, req.Storage)
err = p.Rotate(ctx, req.Storage, b.GetRandomReader())
p.Unlock()
return nil, err

View File

@@ -247,7 +247,7 @@ func (b *backend) pathSignWrite(ctx context.Context, req *logical.Request, d *fr
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}
@@ -456,7 +456,7 @@ func (b *backend) pathVerifyWrite(ctx context.Context, req *logical.Request, d *
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -58,7 +58,7 @@ func testTransit_SignVerify_ECDSA(t *testing.T, bits int) {
p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "foo",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -274,11 +274,11 @@ func testTransit_SignVerify_ECDSA(t *testing.T, bits int) {
signRequest(req, true, "")
// Rotate and set min decryption version
err = p.Rotate(context.Background(), storage)
err = p.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
err = p.Rotate(context.Background(), storage)
err = p.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -378,7 +378,7 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
fooP, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "foo",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -386,7 +386,7 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
barP, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{
Storage: storage,
Name: "bar",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -566,11 +566,11 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
sig = signRequest(req, true, "bar")
// Rotate and set min decryption version
err = fooP.Rotate(context.Background(), storage)
err = fooP.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
err = fooP.Rotate(context.Background(), storage)
err = fooP.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
@@ -578,11 +578,11 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
if err = fooP.Persist(context.Background(), storage); err != nil {
t.Fatal(err)
}
err = barP.Rotate(context.Background(), storage)
err = barP.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
err = barP.Rotate(context.Background(), storage)
err = barP.Rotate(context.Background(), storage, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}

View File

@@ -43,7 +43,7 @@ func (b *backend) pathTrimUpdate() framework.OperationFunc {
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
}, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -39,7 +39,7 @@ func TestTransit_Trim(t *testing.T) {
p, _, err := b.lm.GetPolicy(namespace.RootContext(nil), keysutil.PolicyRequest{
Storage: storage,
Name: "aes",
})
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}

View File

@@ -32,6 +32,7 @@ type AuthEnableCommand struct {
flagOptions map[string]string
flagLocal bool
flagSealWrap bool
flagExternalEntropyAccess bool
flagTokenType string
flagVersion int
}
@@ -176,6 +177,13 @@ func (c *AuthEnableCommand) Flags() *FlagSets {
Usage: "Enable seal wrapping of critical values in the secrets engine.",
})
f.BoolVar(&BoolVar{
Name: "external-entropy-access",
Target: &c.flagExternalEntropyAccess,
Default: false,
Usage: "Enable auth method to access Vault's external entropy source.",
})
f.StringVar(&StringVar{
Name: flagNameTokenType,
Target: &c.flagTokenType,
@@ -255,6 +263,7 @@ func (c *AuthEnableCommand) Run(args []string) int {
Description: c.flagDescription,
Local: c.flagLocal,
SealWrap: c.flagSealWrap,
ExternalEntropyAccess: c.flagExternalEntropyAccess,
Config: api.AuthConfigInput{
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),

View File

@@ -143,7 +143,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
}
}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | Options | Description | UUID"}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID"}
for _, path := range paths {
mount := auths[path]
@@ -160,7 +160,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
pluginName = mount.Config.PluginName
}
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s | %s",
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s | %s | %s",
path,
pluginName,
mount.Accessor,
@@ -169,6 +169,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
mount.Config.TokenType,
replication,
mount.SealWrap,
mount.ExternalEntropyAccess,
mount.Options,
mount.Description,
mount.UUID,

View File

@@ -33,6 +33,7 @@ type SecretsEnableCommand struct {
flagOptions map[string]string
flagLocal bool
flagSealWrap bool
flagExternalEntropyAccess bool
flagVersion int
}
@@ -192,6 +193,13 @@ func (c *SecretsEnableCommand) Flags() *FlagSets {
Usage: "Enable seal wrapping of critical values in the secrets engine.",
})
f.BoolVar(&BoolVar{
Name: "external-entropy-access",
Target: &c.flagExternalEntropyAccess,
Default: false,
Usage: "Enable secrets engine to access Vault's external entropy source.",
})
f.IntVar(&IntVar{
Name: "version",
Target: &c.flagVersion,
@@ -267,6 +275,7 @@ func (c *SecretsEnableCommand) Run(args []string) int {
Description: c.flagDescription,
Local: c.flagLocal,
SealWrap: c.flagSealWrap,
ExternalEntropyAccess: c.flagExternalEntropyAccess,
Config: api.MountConfigInput{
DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(),
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),

View File

@@ -143,7 +143,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
}
}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | Options | Description | UUID "}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID "}
for _, path := range paths {
mount := mounts[path]
@@ -160,7 +160,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
pluginName = mount.Config.PluginName
}
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s | %s",
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s | %s | %s",
path,
pluginName,
mount.Accessor,
@@ -169,6 +169,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
mount.Config.ForceNoCache,
replication,
mount.SealWrap,
mount.ExternalEntropyAccess,
mount.Options,
mount.Description,
mount.UUID,

View File

@@ -1006,6 +1006,13 @@ func (c *ServerCommand) Run(args []string) int {
return 1
}
// prepare a secure random reader for core
secureRandomReader, err := createSecureRandomReaderFunc(config, &barrierSeal)
if err != nil {
c.UI.Error(err.Error())
return 1
}
coreConfig := &vault.CoreConfig{
RawConfig: config,
Physical: backend,
@@ -1033,6 +1040,7 @@ func (c *ServerCommand) Run(args []string) int {
BuiltinRegistry: builtinplugins.Registry,
DisableKeyEncodingChecks: config.DisablePrintableCheck,
MetricsHelper: metricsHelper,
SecureRandomReader: secureRandomReader,
}
if c.flagDev {
coreConfig.DevToken = c.flagDevRootTokenID

View File

@@ -12,7 +12,6 @@ import (
"time"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
@@ -30,6 +29,7 @@ type Config struct {
HAStorage *Storage `hcl:"-"`
Seals []*Seal `hcl:"-"`
Entropy *Entropy `hcl:"-"`
CacheSize int `hcl:"cache_size"`
DisableCache bool `hcl:"-"`
@@ -125,6 +125,18 @@ func (l *Listener) GoString() string {
return fmt.Sprintf("*%#v", *l)
}
// Entropy contains Entropy configuration for the server
type EntropyMode int
const (
Unknown EntropyMode = iota
Augmentation
)
type Entropy struct {
Mode EntropyMode
}
// Storage is the underlying storage configuration for the server.
type Storage struct {
Type string
@@ -279,6 +291,11 @@ func (c *Config) Merge(c2 *Config) *Config {
result.HAStorage = c2.HAStorage
}
result.Entropy = c.Entropy
if c2.Entropy != nil {
result.Entropy = c2.Entropy
}
for _, s := range c.Seals {
result.Seals = append(result.Seals, s)
}
@@ -579,6 +596,12 @@ func ParseConfig(d string) (*Config, error) {
}
}
if o := list.Filter("entropy"); len(o.Items) > 0 {
if err := parseEntropy(&result, o, "entropy"); err != nil {
return nil, errwrap.Wrapf("error parsing 'entropy': {{err}}", err)
}
}
if o := list.Filter("listener"); len(o.Items) > 0 {
if err := parseListeners(&result, o); err != nil {
return nil, errwrap.Wrapf("error parsing 'listener': {{err}}", err)
@@ -821,7 +844,6 @@ func parseSeals(result *Config, list *ast.ObjectList, blockName string) error {
if err := hcl.DecodeObject(&m, item.Val); err != nil {
return multierror.Prefix(err, fmt.Sprintf("seal.%s:", key))
}
var disabled bool
var err error
if v, ok := m["disabled"]; ok {

View File

@@ -1,487 +1,39 @@
// +build !enterprise
package server
import (
"reflect"
"strings"
"testing"
"time"
"github.com/go-test/deep"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
)
func TestLoadConfigFile(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
RedirectAddr: "foo",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
RedirectAddr: "snafu",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
Telemetry: &Telemetry{
StatsdAddr: "bar",
StatsiteAddr: "foo",
DisableHostname: false,
DogStatsDAddr: "127.0.0.1:7254",
DogStatsDTags: []string{"tag_1:val_1", "tag_2:val_2"},
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
DisableCache: true,
DisableCacheRaw: true,
DisableMlock: true,
DisableMlockRaw: true,
DisablePrintableCheckRaw: true,
DisablePrintableCheck: true,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
PidFile: "./pidfile",
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
testLoadConfigFile(t)
}
func TestLoadConfigFile_topLevel(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config2.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
RedirectAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
RedirectAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
Telemetry: &Telemetry{
StatsdAddr: "bar",
StatsiteAddr: "foo",
DisableHostname: false,
DogStatsDAddr: "127.0.0.1:7254",
DogStatsDTags: []string{"tag_1:val_1", "tag_2:val_2"},
PrometheusRetentionTime: 30 * time.Second,
PrometheusRetentionTimeRaw: "30s",
},
DisableCache: true,
DisableCacheRaw: true,
DisableMlock: true,
DisableMlockRaw: true,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
PidFile: "./pidfile",
APIAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
testLoadConfigFile_topLevel(t,nil)
}
func TestLoadConfigFile_json(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config.hcl.json")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
DisableClustering: true,
},
ClusterCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
Telemetry: &Telemetry{
StatsiteAddr: "baz",
StatsdAddr: "",
DisableHostname: false,
CirconusAPIToken: "",
CirconusAPIApp: "",
CirconusAPIURL: "",
CirconusSubmissionInterval: "",
CirconusCheckSubmissionURL: "",
CirconusCheckID: "",
CirconusCheckForceMetricActivation: "",
CirconusCheckInstanceID: "",
CirconusCheckSearchTag: "",
CirconusCheckDisplayName: "",
CirconusCheckTags: "",
CirconusBrokerID: "",
CirconusBrokerSelectTag: "",
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
DisableCacheRaw: interface{}(nil),
DisableMlockRaw: interface{}(nil),
EnableUI: true,
EnableUIRaw: true,
PidFile: "./pidfile",
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
testLoadConfigFile_json(t)
}
func TestLoadConfigFile_json2(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config2.hcl.json")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:444",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
CacheSize: 45678,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
Telemetry: &Telemetry{
StatsiteAddr: "foo",
StatsdAddr: "bar",
DisableHostname: true,
CirconusAPIToken: "0",
CirconusAPIApp: "vault",
CirconusAPIURL: "http://api.circonus.com/v2",
CirconusSubmissionInterval: "10s",
CirconusCheckSubmissionURL: "https://someplace.com/metrics",
CirconusCheckID: "0",
CirconusCheckForceMetricActivation: "true",
CirconusCheckInstanceID: "node1:vault",
CirconusCheckSearchTag: "service:vault",
CirconusCheckDisplayName: "node1:vault",
CirconusCheckTags: "cat1:tag1,cat2:tag2",
CirconusBrokerID: "0",
CirconusBrokerSelectTag: "dc:sfo",
PrometheusRetentionTime: 30 * time.Second,
PrometheusRetentionTimeRaw: "30s",
},
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
testLoadConfigFile_json2(t,nil)
}
func TestLoadConfigDir(t *testing.T) {
config, err := LoadConfigDir("./test-fixtures/config-dir")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
DisableCache: true,
DisableMlock: true,
DisableClustering: false,
DisableClusteringRaw: false,
APIAddr: "https://vault.local",
ClusterAddr: "https://127.0.0.1:444",
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
RedirectAddr: "https://vault.local",
ClusterAddr: "https://127.0.0.1:444",
DisableClustering: false,
},
EnableUI: true,
EnableRawEndpoint: true,
Telemetry: &Telemetry{
StatsiteAddr: "qux",
StatsdAddr: "baz",
DisableHostname: true,
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
MaxLeaseTTL: 10 * time.Hour,
DefaultLeaseTTL: 10 * time.Hour,
ClusterName: "testcluster",
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
testLoadConfigDir(t)
}
func TestConfig_Sanitized(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config3.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
sanitizedConfig := config.Sanitized()
expected := map[string]interface{}{
"api_addr": "top_level_api_addr",
"cache_size": 0,
"cluster_addr": "top_level_cluster_addr",
"cluster_cipher_suites": "",
"cluster_name": "testcluster",
"default_lease_ttl": 10 * time.Hour,
"default_max_request_duration": 0 * time.Second,
"disable_cache": true,
"disable_clustering": false,
"disable_indexing": false,
"disable_mlock": true,
"disable_performance_standby": false,
"disable_printable_check": false,
"disable_sealwrap": true,
"raw_storage_endpoint": true,
"enable_ui": true,
"ha_storage": map[string]interface{}{
"cluster_addr": "top_level_cluster_addr",
"disable_clustering": true,
"redirect_addr": "top_level_api_addr",
"type": "consul"},
"listeners": []interface{}{
map[string]interface{}{
"config": map[string]interface{}{
"address": "127.0.0.1:443",
},
"type": "tcp",
},
},
"log_format": "",
"log_level": "",
"max_lease_ttl": 10 * time.Hour,
"pid_file": "./pidfile",
"plugin_directory": "",
"seals": []interface{}{
map[string]interface{}{
"disabled": false,
"type": "awskms",
},
},
"storage": map[string]interface{}{
"cluster_addr": "top_level_cluster_addr",
"disable_clustering": false,
"redirect_addr": "top_level_api_addr",
"type": "consul",
},
"telemetry": map[string]interface{}{
"circonus_api_app": "",
"circonus_api_token": "",
"circonus_api_url": "",
"circonus_broker_id": "",
"circonus_broker_select_tag": "",
"circonus_check_display_name": "",
"circonus_check_force_metric_activation": "",
"circonus_check_id": "",
"circonus_check_instance_id": "",
"circonus_check_search_tag": "",
"circonus_submission_url": "",
"circonus_check_tags": "",
"circonus_submission_interval": "",
"disable_hostname": false,
"dogstatsd_addr": "",
"dogstatsd_tags": []string(nil),
"prometheus_retention_time": 24 * time.Hour,
"stackdriver_location": "",
"stackdriver_namespace": "",
"stackdriver_project_id": "",
"statsd_address": "bar",
"statsite_address": ""},
}
if diff := deep.Equal(sanitizedConfig, expected); len(diff) > 0 {
t.Fatalf("bad, diff: %#v", diff)
}
testConfig_Sanitized(t)
}
func TestParseListeners(t *testing.T) {
obj, _ := hcl.Parse(strings.TrimSpace(`
listener "tcp" {
address = "127.0.0.1:443"
cluster_address = "127.0.0.1:8201"
tls_disable = false
tls_cert_file = "./certs/server.crt"
tls_key_file = "./certs/server.key"
tls_client_ca_file = "./certs/rootca.crt"
tls_min_version = "tls12"
tls_require_and_verify_client_cert = true
tls_disable_client_certs = true
}`))
var config Config
list, _ := obj.Node.(*ast.ObjectList)
objList := list.Filter("listener")
parseListeners(&config, objList)
listeners := config.Listeners
if len(listeners) == 0 {
t.Fatalf("expected at least one listener in the config")
}
listener := listeners[0]
if listener.Type != "tcp" {
t.Fatalf("expected tcp listener in the config")
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
"cluster_address": "127.0.0.1:8201",
"tls_disable": false,
"tls_cert_file": "./certs/server.crt",
"tls_key_file": "./certs/server.key",
"tls_client_ca_file": "./certs/rootca.crt",
"tls_min_version": "tls12",
"tls_require_and_verify_client_cert": true,
"tls_disable_client_certs": true,
},
},
},
}
if !reflect.DeepEqual(config, *expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, *expected)
testParseListeners(t)
}
func TestParseEntropy(t *testing.T){
testParseEntropy(t,true)
}

View File

@@ -0,0 +1,559 @@
package server
import (
"fmt"
"reflect"
"strings"
"testing"
"time"
"github.com/go-test/deep"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
)
func testLoadConfigFile_topLevel(t *testing.T, entropy *Entropy) {
config, err := LoadConfigFile("./test-fixtures/config2.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
RedirectAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
RedirectAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
Telemetry: &Telemetry{
StatsdAddr: "bar",
StatsiteAddr: "foo",
DisableHostname: false,
DogStatsDAddr: "127.0.0.1:7254",
DogStatsDTags: []string{"tag_1:val_1", "tag_2:val_2"},
PrometheusRetentionTime: 30 * time.Second,
PrometheusRetentionTimeRaw: "30s",
},
DisableCache: true,
DisableCacheRaw: true,
DisableMlock: true,
DisableMlockRaw: true,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
PidFile: "./pidfile",
APIAddr: "top_level_api_addr",
ClusterAddr: "top_level_cluster_addr",
}
if entropy != nil {
expected.Entropy = entropy
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
}
func testLoadConfigFile_json2(t *testing.T, entropy *Entropy) {
config, err := LoadConfigFile("./test-fixtures/config2.hcl.json")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:444",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
CacheSize: 45678,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
Telemetry: &Telemetry{
StatsiteAddr: "foo",
StatsdAddr: "bar",
DisableHostname: true,
CirconusAPIToken: "0",
CirconusAPIApp: "vault",
CirconusAPIURL: "http://api.circonus.com/v2",
CirconusSubmissionInterval: "10s",
CirconusCheckSubmissionURL: "https://someplace.com/metrics",
CirconusCheckID: "0",
CirconusCheckForceMetricActivation: "true",
CirconusCheckInstanceID: "node1:vault",
CirconusCheckSearchTag: "service:vault",
CirconusCheckDisplayName: "node1:vault",
CirconusCheckTags: "cat1:tag1,cat2:tag2",
CirconusBrokerID: "0",
CirconusBrokerSelectTag: "dc:sfo",
PrometheusRetentionTime: 30 * time.Second,
PrometheusRetentionTimeRaw: "30s",
},
}
if entropy != nil {
expected.Entropy = entropy
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
}
func testParseEntropy(t *testing.T, oss bool) {
var tests = []struct {
inConfig string
outErr error
outEntropy Entropy
}{
{
inConfig: `entropy "seal" {
mode = "augmentation"
}`,
outErr: nil,
outEntropy: Entropy{Augmentation},
},
{
inConfig: `entropy "seal" {
mode = "a_mode_that_is_not_supported"
}`,
outErr: fmt.Errorf("the specified entropy mode %q is not supported", "a_mode_that_is_not_supported"),
},
{
inConfig: `entropy "device_that_is_not_supported" {
mode = "augmentation"
}`,
outErr: fmt.Errorf("only the %q type of external entropy is supported", "seal"),
},
{
inConfig: `entropy "seal" {
mode = "augmentation"
}
entropy "seal" {
mode = "augmentation"
}`,
outErr: fmt.Errorf("only one %q block is permitted", "entropy"),
},
}
var config Config
for _, test := range tests {
obj, _ := hcl.Parse(strings.TrimSpace(test.inConfig))
list, _ := obj.Node.(*ast.ObjectList)
objList := list.Filter("entropy")
err := parseEntropy(&config, objList, "entropy")
// validate the error, both should be nil or have the same Error()
switch {
case oss:
if config.Entropy != nil {
t.Fatalf("parsing Entropy should not be possible in oss but got a non-nil config.Entropy: %#v", config.Entropy)
}
case err != nil && test.outErr != nil:
if err.Error() != test.outErr.Error() {
t.Fatalf("error mismatch: expected %#v got %#v", err, test.outErr)
}
case err != test.outErr:
t.Fatalf("error mismatch: expected %#v got %#v", err, test.outErr)
case err == nil && config.Entropy != nil && *config.Entropy != test.outEntropy:
fmt.Printf("\n config.Entropy: %#v",config.Entropy)
t.Fatalf("entropy config mismatch: expected %#v got %#v", test.outEntropy, *config.Entropy)
}
}
}
func testLoadConfigFile(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
RedirectAddr: "foo",
Config: map[string]string{
"foo": "bar",
},
},
HAStorage: &Storage{
Type: "consul",
RedirectAddr: "snafu",
Config: map[string]string{
"bar": "baz",
},
DisableClustering: true,
},
Telemetry: &Telemetry{
StatsdAddr: "bar",
StatsiteAddr: "foo",
DisableHostname: false,
DogStatsDAddr: "127.0.0.1:7254",
DogStatsDTags: []string{"tag_1:val_1", "tag_2:val_2"},
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
DisableCache: true,
DisableCacheRaw: true,
DisableMlock: true,
DisableMlockRaw: true,
DisablePrintableCheckRaw: true,
DisablePrintableCheck: true,
EnableUI: true,
EnableUIRaw: true,
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
Entropy: nil,
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
PidFile: "./pidfile",
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
}
func testLoadConfigFile_json(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config.hcl.json")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
DisableClustering: true,
},
ClusterCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
Telemetry: &Telemetry{
StatsiteAddr: "baz",
StatsdAddr: "",
DisableHostname: false,
CirconusAPIToken: "",
CirconusAPIApp: "",
CirconusAPIURL: "",
CirconusSubmissionInterval: "",
CirconusCheckSubmissionURL: "",
CirconusCheckID: "",
CirconusCheckForceMetricActivation: "",
CirconusCheckInstanceID: "",
CirconusCheckSearchTag: "",
CirconusCheckDisplayName: "",
CirconusCheckTags: "",
CirconusBrokerID: "",
CirconusBrokerSelectTag: "",
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
DefaultLeaseTTLRaw: "10h",
ClusterName: "testcluster",
DisableCacheRaw: interface{}(nil),
DisableMlockRaw: interface{}(nil),
EnableUI: true,
EnableUIRaw: true,
PidFile: "./pidfile",
EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
DisableSealWrap: true,
DisableSealWrapRaw: true,
Entropy: nil,
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
}
func testLoadConfigDir(t *testing.T) {
config, err := LoadConfigDir("./test-fixtures/config-dir")
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &Config{
DisableCache: true,
DisableMlock: true,
DisableClustering: false,
DisableClusteringRaw: false,
APIAddr: "https://vault.local",
ClusterAddr: "https://127.0.0.1:444",
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
},
},
},
Storage: &Storage{
Type: "consul",
Config: map[string]string{
"foo": "bar",
},
RedirectAddr: "https://vault.local",
ClusterAddr: "https://127.0.0.1:444",
DisableClustering: false,
},
EnableUI: true,
EnableRawEndpoint: true,
Telemetry: &Telemetry{
StatsiteAddr: "qux",
StatsdAddr: "baz",
DisableHostname: true,
PrometheusRetentionTime: prometheusDefaultRetentionTime,
},
MaxLeaseTTL: 10 * time.Hour,
DefaultLeaseTTL: 10 * time.Hour,
ClusterName: "testcluster",
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
}
}
func testConfig_Sanitized(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config3.hcl")
if err != nil {
t.Fatalf("err: %s", err)
}
sanitizedConfig := config.Sanitized()
expected := map[string]interface{}{
"api_addr": "top_level_api_addr",
"cache_size": 0,
"cluster_addr": "top_level_cluster_addr",
"cluster_cipher_suites": "",
"cluster_name": "testcluster",
"default_lease_ttl": 10 * time.Hour,
"default_max_request_duration": 0 * time.Second,
"disable_cache": true,
"disable_clustering": false,
"disable_indexing": false,
"disable_mlock": true,
"disable_performance_standby": false,
"disable_printable_check": false,
"disable_sealwrap": true,
"raw_storage_endpoint": true,
"enable_ui": true,
"ha_storage": map[string]interface{}{
"cluster_addr": "top_level_cluster_addr",
"disable_clustering": true,
"redirect_addr": "top_level_api_addr",
"type": "consul"},
"listeners": []interface{}{
map[string]interface{}{
"config": map[string]interface{}{
"address": "127.0.0.1:443",
},
"type": "tcp",
},
},
"log_format": "",
"log_level": "",
"max_lease_ttl": 10 * time.Hour,
"pid_file": "./pidfile",
"plugin_directory": "",
"seals": []interface{}{
map[string]interface{}{
"disabled": false,
"type": "awskms",
},
},
"storage": map[string]interface{}{
"cluster_addr": "top_level_cluster_addr",
"disable_clustering": false,
"redirect_addr": "top_level_api_addr",
"type": "consul",
},
"telemetry": map[string]interface{}{
"circonus_api_app": "",
"circonus_api_token": "",
"circonus_api_url": "",
"circonus_broker_id": "",
"circonus_broker_select_tag": "",
"circonus_check_display_name": "",
"circonus_check_force_metric_activation": "",
"circonus_check_id": "",
"circonus_check_instance_id": "",
"circonus_check_search_tag": "",
"circonus_submission_url": "",
"circonus_check_tags": "",
"circonus_submission_interval": "",
"disable_hostname": false,
"dogstatsd_addr": "",
"dogstatsd_tags": []string(nil),
"prometheus_retention_time": 24 * time.Hour,
"stackdriver_location": "",
"stackdriver_namespace": "",
"stackdriver_project_id": "",
"statsd_address": "bar",
"statsite_address": ""},
}
if diff := deep.Equal(sanitizedConfig, expected); len(diff) > 0 {
t.Fatalf("bad, diff: %#v", diff)
}
}
func testParseListeners(t *testing.T) {
obj, _ := hcl.Parse(strings.TrimSpace(`
listener "tcp" {
address = "127.0.0.1:443"
cluster_address = "127.0.0.1:8201"
tls_disable = false
tls_cert_file = "./certs/server.crt"
tls_key_file = "./certs/server.key"
tls_client_ca_file = "./certs/rootca.crt"
tls_min_version = "tls12"
tls_require_and_verify_client_cert = true
tls_disable_client_certs = true
}`))
var config Config
list, _ := obj.Node.(*ast.ObjectList)
objList := list.Filter("listener")
parseListeners(&config, objList)
listeners := config.Listeners
if len(listeners) == 0 {
t.Fatalf("expected at least one listener in the config")
}
listener := listeners[0]
if listener.Type != "tcp" {
t.Fatalf("expected tcp listener in the config")
}
expected := &Config{
Listeners: []*Listener{
&Listener{
Type: "tcp",
Config: map[string]interface{}{
"address": "127.0.0.1:443",
"cluster_address": "127.0.0.1:8201",
"tls_disable": false,
"tls_cert_file": "./certs/server.crt",
"tls_key_file": "./certs/server.key",
"tls_client_ca_file": "./certs/rootca.crt",
"tls_min_version": "tls12",
"tls_require_and_verify_client_cert": true,
"tls_disable_client_certs": true,
},
},
},
}
if !reflect.DeepEqual(config, *expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, *expected)
}
}

View File

@@ -0,0 +1,13 @@
package server
import (
"github.com/hashicorp/hcl/hcl/ast"
)
var(
parseEntropy = parseEntropyOSS
)
func parseEntropyOSS(result *Config, list *ast.ObjectList, blockName string) error {
return nil
}

View File

@@ -29,6 +29,10 @@ telemetry {
prometheus_retention_time = "30s"
}
entropy "seal" {
mode = "augmentation"
}
max_lease_ttl = "10h"
default_lease_ttl = "10h"
cluster_name = "testcluster"

View File

@@ -44,5 +44,10 @@
"circonus_broker_id": "0",
"circonus_broker_select_tag": "dc:sfo",
"prometheus_retention_time": "30s"
},
"entropy": {
"seal": {
"mode": "augmentation"
}
}
}

View File

@@ -2,9 +2,12 @@ package command
import (
"context"
"crypto/rand"
"fmt"
"io"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/command/server"
"github.com/hashicorp/vault/vault"
vaultseal "github.com/hashicorp/vault/vault/seal"
shamirseal "github.com/hashicorp/vault/vault/seal/shamir"
@@ -13,8 +16,13 @@ import (
var (
onEnterprise = false
createSecureRandomReaderFunc = createSecureRandomReader
)
func createSecureRandomReader(config *server.Config, seal *vault.Seal) (io.Reader, error) {
return rand.Reader, nil
}
func adjustCoreForSealMigration(logger log.Logger, core *vault.Core, barrierSeal, unwrapSeal vault.Seal) error {
existBarrierSealConfig, existRecoverySealConfig, err := core.PhysicalSealConfigs(context.Background())
if err != nil {

7
go.mod
View File

@@ -25,7 +25,6 @@ require (
github.com/aws/aws-sdk-go v1.19.39
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/boombuler/barcode v1.0.0 // indirect
github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c
@@ -61,7 +60,7 @@ require (
github.com/hashicorp/go-rootcerts v1.0.1
github.com/hashicorp/go-sockaddr v1.0.2
github.com/hashicorp/go-syslog v1.0.0
github.com/hashicorp/go-uuid v1.0.1
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8
github.com/hashicorp/golang-lru v0.5.3
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/nomad/api v0.0.0-20190412184103-1c38ced33adf
@@ -81,7 +80,7 @@ require (
github.com/hashicorp/vault-plugin-secrets-azure v0.5.2-0.20190814210135-54b8afbc42ae
github.com/hashicorp/vault-plugin-secrets-gcp v0.5.3-0.20190814210141-d2086ff79b04
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.2-0.20190814210149-315cdbf5de6e
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190814210155-e060c2a001a8
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20191003164552-6600ec024c24
github.com/hashicorp/vault/api v1.0.5-0.20190919134245-4eefe0ebe1a1
github.com/hashicorp/vault/sdk v0.1.14-0.20190919081434-645ac174deeb
github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4
@@ -113,7 +112,7 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.8.1
github.com/posener/complete v1.2.1
github.com/pquerna/otp v1.1.0
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
github.com/prometheus/common v0.2.0
github.com/ryanuber/columnize v2.1.0+incompatible

20
go.sum
View File

@@ -75,8 +75,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f h1:ZMEzE7R0WNqgbHplzSBaYJhJi5AZWTCK9baU0ebzG6g=
github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f/go.mod h1:HQhVmdUf7dBNwIIdBTivnCDxcf6IZY3/zrb+uKSJz6Y=
@@ -293,8 +293,6 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-raftchunking v0.6.2 h1:imj6CVkwXj6VzgXZQvzS+fSrkbFCzlJ2t00F3PacnuU=
github.com/hashicorp/go-raftchunking v0.6.2/go.mod h1:cGlg3JtDy7qy6c/3Bu660Mic1JF+7lWqIwCFSb08fX0=
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a h1:FmnBDwGwlTgugDGbVxwV8UavqSMACbGrUpfc98yFLR4=
github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod h1:xbXnmKqX9/+RhPkJ4zrEx4738HacP72aaUPlT2RZ4sU=
github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s=
@@ -315,6 +313,8 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8 h1:PKbxRbsOP7R3f/TpdqcgXrO69T3yd9nLoR+RMRUxSxA=
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
@@ -334,8 +334,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/nomad/api v0.0.0-20190412184103-1c38ced33adf h1:U/40PQvWkaXCDdK9QHKf1pVDVcA+NIDVbzzonFGkgIA=
github.com/hashicorp/nomad/api v0.0.0-20190412184103-1c38ced33adf/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk=
github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
github.com/hashicorp/raft v1.1.1 h1:HJr7UE1x/JrJSc9Oy6aDBHtNHUUBHjcQjTgvUVihoZs=
github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft v1.1.2-0.20191002163536-9c6bd3e3eb17 h1:p+2EISNdFCnD9R+B4xCiqSn429MCFtvM41aHJDJ6qW4=
github.com/hashicorp/raft v1.1.2-0.20191002163536-9c6bd3e3eb17/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
@@ -363,8 +361,6 @@ github.com/hashicorp/vault-plugin-auth-oci v0.0.0-20190904175623-97c0c0187c5c h1
github.com/hashicorp/vault-plugin-auth-oci v0.0.0-20190904175623-97c0c0187c5c/go.mod h1:YAl51RsYRihPbSdnug1NsvutzbRVfrZ12FjEIvSiOTs=
github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93 h1:kXTV1ImOPgDGZxAlbEQfiXgnZY/34vfgnZVhI/tscmg=
github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93/go.mod h1:N9XpfMXjeLHBgUd8iy4avOC4mCSqUC7B/R8AtCYhcfE=
github.com/hashicorp/vault-plugin-secrets-ad v0.5.3-0.20190814210122-0f2fd536b250 h1:+mm2cM5msg/USImbvnMS2yzCMBYMCO3CrvsATWGtHtY=
github.com/hashicorp/vault-plugin-secrets-ad v0.5.3-0.20190814210122-0f2fd536b250/go.mod h1:F8hKHqcB7stN2OhnqE3emwFYtKO0IDNxMBbPs2n8vr0=
github.com/hashicorp/vault-plugin-secrets-ad v0.6.0 h1:N0AtdV3w6VCtU7rZiTbPxsxhluJXrzpYH9B1pLZhG6g=
github.com/hashicorp/vault-plugin-secrets-ad v0.6.0/go.mod h1:qm2QDW9KNY+pFoxBEYGYvcHnVjdiOr3tXeO9DMeo3mI=
github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.2-0.20190814210129-4d18bec92f56 h1:PGE26//x1eiAbZ1ExffhKa4y9xgDKLd9BHDZRkOzbEY=
@@ -375,8 +371,8 @@ github.com/hashicorp/vault-plugin-secrets-gcp v0.5.3-0.20190814210141-d2086ff79b
github.com/hashicorp/vault-plugin-secrets-gcp v0.5.3-0.20190814210141-d2086ff79b04/go.mod h1:Sc+ba3kscakE5a/pi8JJhWvXWok3cpt1P77DApmUuDc=
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.2-0.20190814210149-315cdbf5de6e h1:RjQBOFneGwxhHsymNtbEUJXAjMO74GlZcmUrGqJnYxY=
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.2-0.20190814210149-315cdbf5de6e/go.mod h1:5prAHuCcBiyv+xfGBviTVYeDQUhmQYN7WrxC2gMRWeQ=
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190814210155-e060c2a001a8 h1:8nZOMqGQQiuWNld162nxUvM4/7EW4NOO9gpyp7LCC84=
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190814210155-e060c2a001a8/go.mod h1:5ksi71TrWxz7ZRo0MIlsry2lYDlZQyLalN4cF8a4vnk=
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20191003164552-6600ec024c24 h1:ZGxFf28+4ElvBJKPgms5DigDFtPM90QhAif46uPQjVg=
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20191003164552-6600ec024c24/go.mod h1:5ksi71TrWxz7ZRo0MIlsry2lYDlZQyLalN4cF8a4vnk=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
@@ -532,8 +528,8 @@ github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6D
github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/otp v1.1.0 h1:q2gMsMuMl3JzneUaAX1MRGxLvOG6bzXV51hivBaStf0=
github.com/pquerna/otp v1.1.0/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk=
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d h1:PinQItctnaL2LtkaSM678+ZLLy5TajwOeXzWvYC7tII=
github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=

View File

@@ -271,6 +271,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -283,6 +284,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -296,6 +298,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -308,6 +311,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -321,6 +325,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -333,6 +338,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -346,6 +352,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -358,6 +365,7 @@ func TestSysMounts_headerAuth(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),

View File

@@ -29,6 +29,7 @@ func TestSysAuth(t *testing.T) {
"token/": map[string]interface{}{
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -43,6 +44,7 @@ func TestSysAuth(t *testing.T) {
"token/": map[string]interface{}{
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -103,6 +105,7 @@ func TestSysEnableAuth(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "noop",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -116,6 +119,7 @@ func TestSysEnableAuth(t *testing.T) {
"token/": map[string]interface{}{
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -130,6 +134,7 @@ func TestSysEnableAuth(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "noop",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -143,6 +148,7 @@ func TestSysEnableAuth(t *testing.T) {
"token/": map[string]interface{}{
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -212,6 +218,7 @@ func TestSysDisableAuth(t *testing.T) {
},
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"local": false,
"seal_wrap": false,
"options": interface{}(nil),
@@ -226,6 +233,7 @@ func TestSysDisableAuth(t *testing.T) {
},
"description": "token based credentials",
"type": "token",
"external_entropy_access": false,
"local": false,
"seal_wrap": false,
"options": interface{}(nil),

View File

@@ -31,6 +31,7 @@ func TestSysMounts(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -43,6 +44,7 @@ func TestSysMounts(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -56,6 +58,7 @@ func TestSysMounts(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -68,6 +71,7 @@ func TestSysMounts(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -81,6 +85,7 @@ func TestSysMounts(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -93,6 +98,7 @@ func TestSysMounts(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -106,6 +112,7 @@ func TestSysMounts(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -118,6 +125,7 @@ func TestSysMounts(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -178,6 +186,7 @@ func TestSysMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -190,6 +199,7 @@ func TestSysMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -202,6 +212,7 @@ func TestSysMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -215,6 +226,7 @@ func TestSysMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -227,6 +239,7 @@ func TestSysMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -240,6 +253,7 @@ func TestSysMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -252,6 +266,7 @@ func TestSysMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -264,6 +279,7 @@ func TestSysMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -277,6 +293,7 @@ func TestSysMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -289,6 +306,7 @@ func TestSysMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -369,6 +387,7 @@ func TestSysRemount(t *testing.T) {
"bar/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -381,6 +400,7 @@ func TestSysRemount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -393,6 +413,7 @@ func TestSysRemount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -406,6 +427,7 @@ func TestSysRemount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -418,6 +440,7 @@ func TestSysRemount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -431,6 +454,7 @@ func TestSysRemount(t *testing.T) {
"bar/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -443,6 +467,7 @@ func TestSysRemount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -455,6 +480,7 @@ func TestSysRemount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -468,6 +494,7 @@ func TestSysRemount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -480,6 +507,7 @@ func TestSysRemount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -540,6 +568,7 @@ func TestSysUnmount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -552,6 +581,7 @@ func TestSysUnmount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -565,6 +595,7 @@ func TestSysUnmount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -577,6 +608,7 @@ func TestSysUnmount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -590,6 +622,7 @@ func TestSysUnmount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -602,6 +635,7 @@ func TestSysUnmount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -615,6 +649,7 @@ func TestSysUnmount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -627,6 +662,7 @@ func TestSysUnmount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -769,6 +805,7 @@ func TestSysTuneMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -781,6 +818,7 @@ func TestSysTuneMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -793,6 +831,7 @@ func TestSysTuneMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -806,6 +845,7 @@ func TestSysTuneMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -818,6 +858,7 @@ func TestSysTuneMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -831,6 +872,7 @@ func TestSysTuneMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -843,6 +885,7 @@ func TestSysTuneMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -855,6 +898,7 @@ func TestSysTuneMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -868,6 +912,7 @@ func TestSysTuneMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -880,6 +925,7 @@ func TestSysTuneMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -966,6 +1012,7 @@ func TestSysTuneMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("259196400"),
"max_lease_ttl": json.Number("259200000"),
@@ -978,6 +1025,7 @@ func TestSysTuneMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -990,6 +1038,7 @@ func TestSysTuneMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1003,6 +1052,7 @@ func TestSysTuneMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1015,6 +1065,7 @@ func TestSysTuneMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1028,6 +1079,7 @@ func TestSysTuneMount(t *testing.T) {
"foo/": map[string]interface{}{
"description": "foo",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("259196400"),
"max_lease_ttl": json.Number("259200000"),
@@ -1040,6 +1092,7 @@ func TestSysTuneMount(t *testing.T) {
"secret/": map[string]interface{}{
"description": "key/value secret storage",
"type": "kv",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1052,6 +1105,7 @@ func TestSysTuneMount(t *testing.T) {
"sys/": map[string]interface{}{
"description": "system endpoints used for control, policy and debugging",
"type": "system",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1065,6 +1119,7 @@ func TestSysTuneMount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@@ -1077,6 +1132,7 @@ func TestSysTuneMount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),

View File

@@ -11,6 +11,7 @@ import (
"crypto/x509/pkix"
"errors"
fmt "fmt"
"io"
"math/big"
mathrand "math/rand"
"net"
@@ -86,8 +87,8 @@ func (k *TLSKeyring) GetActive() *TLSKey {
return nil
}
func GenerateTLSKey() (*TLSKey, error) {
key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
func GenerateTLSKey(reader io.Reader) (*TLSKey, error) {
key, err := ecdsa.GenerateKey(elliptic.P521(), reader)
if err != nil {
return nil, err
}

View File

@@ -2,7 +2,9 @@ package framework
import (
"context"
"crypto/rand"
"fmt"
"io"
"io/ioutil"
"net/http"
"regexp"
@@ -14,6 +16,7 @@ import (
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/helper/entropy"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/helper/license"
"github.com/hashicorp/vault/sdk/helper/logging"
@@ -279,6 +282,17 @@ func (b *Backend) Setup(ctx context.Context, config *logical.BackendConfig) erro
return nil
}
// GetRandomReader returns an io.Reader to use for generating key material in
// backends. If the backend has access to an external entropy source it will
// return that, otherwise it returns crypto/rand.Reader.
func (b *Backend) GetRandomReader() io.Reader {
if sourcer, ok := b.System().(entropy.Sourcer); ok {
return entropy.NewReader(sourcer)
}
return rand.Reader
}
// Logger can be used to get the logger. If no logger has been set,
// the logs will be discarded.
func (b *Backend) Logger() log.Logger {

View File

@@ -16,7 +16,7 @@ require (
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-plugin v1.0.1
github.com/hashicorp/go-sockaddr v1.0.2
github.com/hashicorp/go-uuid v1.0.1
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8
github.com/hashicorp/go-version v1.1.0
github.com/hashicorp/golang-lru v0.5.1
github.com/hashicorp/hcl v1.0.0

View File

@@ -44,6 +44,7 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=

View File

@@ -3,7 +3,9 @@
package base62
import (
"crypto/rand"
uuid "github.com/hashicorp/go-uuid"
"io"
)
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
@@ -12,6 +14,12 @@ const csLen = byte(len(charset))
// Random generates a random string using base-62 characters.
// Resulting entropy is ~5.95 bits/character.
func Random(length int) (string, error) {
return RandomWithReader(length, rand.Reader)
}
// RandomWithReader generates a random string using base-62 characters and a given reader.
// Resulting entropy is ~5.95 bits/character.
func RandomWithReader(length int, reader io.Reader) (string, error) {
if length == 0 {
return "", nil
}
@@ -22,7 +30,7 @@ func Random(length int) (string, error) {
batchSize := length + length/4
for {
buf, err := uuid.GenerateRandomBytes(batchSize)
buf, err := uuid.GenerateRandomBytesWithReader(batchSize, reader)
if err != nil {
return "", err
}

View File

@@ -0,0 +1,36 @@
package entropy
import (
"fmt"
"github.com/hashicorp/errwrap"
)
type Sourcer interface {
GetRandom(bytes int) ([]byte, error)
}
type Reader struct {
source Sourcer
}
func NewReader(source Sourcer) *Reader{
return &Reader{source}
}
// Read reads exactly len(p) bytes from r into p.
// If r returns an error having read at least len(p) bytes, the error is dropped.
// It returns the number of bytes copied and an error if fewer bytes were read.
// On return, n == len(p) if and only if err == nil.
func (r *Reader) Read(p []byte) (n int, err error){
requested := len(p)
randBytes, err := r.source.GetRandom(requested)
delivered := copy(p, randBytes)
if delivered != requested {
if err != nil {
return delivered, errwrap.Wrapf("unable to fill provided buffer with entropy: {{err}}", err)
}
return delivered, fmt.Errorf("unable to fill provided buffer with entropy")
}
return delivered, nil
}

View File

@@ -0,0 +1,87 @@
package entropy
import (
"bytes"
"errors"
"fmt"
"github.com/hashicorp/errwrap"
"testing"
)
type mockSourcer struct{}
type mockSourcerWithError struct{}
type mockSourcerFailureWithError struct{}
type mockSourcerFailureWithoutError struct{}
// simulates a successful sourcer
func (m *mockSourcer) GetRandom(bytes int) ([]byte, error) {
return make([]byte, bytes), nil
}
// simulates a sourcer that reads in the requested number of bytes but encounters an error.
// Read should drop any error if the number of bytes specified were successfully read.
func (m *mockSourcerWithError) GetRandom(bytes int) ([]byte, error) {
return make([]byte, bytes), errors.New("boom but you shouldn't care")
}
func (m *mockSourcerFailureWithError) GetRandom(bytes int) ([]byte, error) {
numRetBytes := bytes - 1
return make([]byte, numRetBytes), fmt.Errorf("requested %d bytes of entropy but only filled %d", bytes, numRetBytes)
}
func (m *mockSourcerFailureWithoutError) GetRandom(bytes int) ([]byte, error) {
numRetBytes := bytes - 1
return make([]byte, numRetBytes), nil
}
func TestRead(t *testing.T) {
var tests = []struct {
sourcer Sourcer
preReadBuff []byte
postReadBuff []byte
outErr error
}{
{
new(mockSourcer),
[]byte{1, 2, 3, 4},
[]byte{0, 0, 0, 0},
nil,
},
{
new(mockSourcerWithError),
[]byte{1, 2, 3, 4},
[]byte{0, 0, 0, 0},
nil,
},
{
new(mockSourcerFailureWithError),
[]byte{1, 2, 3, 4},
nil,
errwrap.Wrapf("unable to fill provided buffer with entropy: {{err}}", fmt.Errorf("requested %d bytes of entropy but only filled %d", 4, 3)),
},
{
new(mockSourcerFailureWithoutError),
[]byte{1, 2, 3, 4},
nil,
fmt.Errorf("unable to fill provided buffer with entropy"),
},
}
for _, test := range tests {
mockReader := NewReader(test.sourcer)
buff := make([]byte, len(test.preReadBuff))
copy(buff, test.preReadBuff)
_, err := mockReader.Read(buff)
// validate the error, both should be nil or have the same Error()
switch {
case err != nil && test.outErr != nil:
if err.Error() != test.outErr.Error() {
t.Fatalf("error mismatch: expected %#v got %#v", err, test.outErr)
}
case err != test.outErr:
t.Fatalf("error mismatch: expected %#v got %#v", err, test.outErr)
case err == nil && !bytes.Equal(buff, test.postReadBuff):
t.Fatalf("after read expected buff to be: %#v but got: %#v", test.postReadBuff, buff)
}
}
}

View File

@@ -2,6 +2,7 @@ package keysutil
import (
"context"
"crypto/rand"
"fmt"
"reflect"
"testing"
@@ -77,7 +78,7 @@ func TestEncryptedKeysStorage_List(t *testing.T) {
ctx := context.Background()
err := policy.Rotate(ctx, s)
err := policy.Rotate(ctx, s, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -159,7 +160,7 @@ func TestEncryptedKeysStorage_CRUD(t *testing.T) {
ctx := context.Background()
err := policy.Rotate(ctx, s)
err := policy.Rotate(ctx, s, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -249,7 +250,7 @@ func BenchmarkEncrytedKeyStorage_List(b *testing.B) {
ctx := context.Background()
err := policy.Rotate(ctx, s)
err := policy.Rotate(ctx, s, rand.Reader)
if err != nil {
b.Fatal(err)
}
@@ -295,7 +296,7 @@ func BenchmarkEncrytedKeyStorage_Put(b *testing.B) {
ctx := context.Background()
err := policy.Rotate(ctx, s)
err := policy.Rotate(ctx, s, rand.Reader)
if err != nil {
b.Fatal(err)
}

View File

@@ -5,6 +5,7 @@ import (
"encoding/base64"
"errors"
"fmt"
"io"
"sync"
"sync/atomic"
"time"
@@ -249,7 +250,7 @@ func (lm *LockManager) BackupPolicy(ctx context.Context, storage logical.Storage
// When the function returns, if caching was disabled, the Policy's lock must
// be unlocked when the caller is done (and it should not be re-locked).
func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *Policy, retUpserted bool, retErr error) {
func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest, rand io.Reader) (retP *Policy, retUpserted bool, retErr error) {
var p *Policy
var err error
var ok bool
@@ -379,7 +380,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
}
// Performs the actual persist and does setup
err = p.Rotate(ctx, req.Storage)
err = p.Rotate(ctx, req.Storage, rand)
if err != nil {
cleanup()
return nil, false, err
@@ -400,7 +401,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
}
if p.NeedsUpgrade() {
if err := p.Upgrade(ctx, req.Storage); err != nil {
if err := p.Upgrade(ctx, req.Storage, rand); err != nil {
cleanup()
return nil, false, err
}

View File

@@ -613,7 +613,7 @@ func (p *Policy) NeedsUpgrade() bool {
return false
}
func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage) (retErr error) {
func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage, randReader io.Reader) (retErr error) {
priorKey := p.Key
priorLatestVersion := p.LatestVersion
priorMinDecryptionVersion := p.MinDecryptionVersion
@@ -670,7 +670,7 @@ func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage) (retErr e
if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
entry := p.Keys[strconv.Itoa(p.LatestVersion)]
hmacKey, err := uuid.GenerateRandomBytes(32)
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
if err != nil {
return err
}
@@ -1371,7 +1371,7 @@ func (p *Policy) VerifySignature(context, input []byte, hashAlgorithm HashType,
}
}
func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr error) {
func (p *Policy) Rotate(ctx context.Context, storage logical.Storage, randReader io.Reader) (retErr error) {
priorLatestVersion := p.LatestVersion
priorMinDecryptionVersion := p.MinDecryptionVersion
var priorKeys keyEntryMap
@@ -1405,7 +1405,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
DeprecatedCreationTime: now.Unix(),
}
hmacKey, err := uuid.GenerateRandomBytes(32)
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
if err != nil {
return err
}
@@ -1418,7 +1418,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
if p.Type == KeyType_AES128_GCM96 {
numBytes = 16
}
newKey, err := uuid.GenerateRandomBytes(numBytes)
newKey, err := uuid.GenerateRandomBytesWithReader(numBytes, randReader)
if err != nil {
return err
}
@@ -1457,7 +1457,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
entry.FormattedPublicKey = string(pemBytes)
case KeyType_ED25519:
pub, pri, err := ed25519.GenerateKey(rand.Reader)
pub, pri, err := ed25519.GenerateKey(randReader)
if err != nil {
return err
}
@@ -1470,7 +1470,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
bitSize = 4096
}
entry.RSAKey, err = rsa.GenerateKey(rand.Reader, bitSize)
entry.RSAKey, err = rsa.GenerateKey(randReader, bitSize)
if err != nil {
return err
}

View File

@@ -7,6 +7,7 @@ import (
"sync"
"testing"
"time"
"crypto/rand"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -67,7 +68,7 @@ func testKeyUpgradeCommon(t *testing.T, lm *LockManager) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -119,7 +120,7 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -135,7 +136,7 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
checkKeys(t, ctx, p, storage, keysArchive, "initial", 1, 1, 1)
for i := 2; i <= 10; i++ {
err = p.Rotate(ctx, storage)
err = p.Rotate(ctx, storage, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -176,7 +177,7 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
p, _, err = lm.GetPolicy(ctx, PolicyRequest{
Storage: storage,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -216,7 +217,7 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
p, _, err = lm.GetPolicy(ctx, PolicyRequest{
Storage: storage,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -249,7 +250,7 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
p, _, err = lm.GetPolicy(ctx, PolicyRequest{
Storage: storage,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -279,7 +280,7 @@ func testArchivingCommon(t *testing.T, lm *LockManager) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -295,7 +296,7 @@ func testArchivingCommon(t *testing.T, lm *LockManager) {
checkKeys(t, ctx, p, storage, keysArchive, "initial", 1, 1, 1)
for i := 2; i <= 10; i++ {
err = p.Rotate(ctx, storage)
err = p.Rotate(ctx, storage, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -433,7 +434,7 @@ func Test_StorageErrorSafety(t *testing.T) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -448,7 +449,7 @@ func Test_StorageErrorSafety(t *testing.T) {
// We use checkKeys here just for sanity; it doesn't really handle cases of
// errors below so we do more targeted testing later
for i := 2; i <= 5; i++ {
err = p.Rotate(ctx, storage)
err = p.Rotate(ctx, storage, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -461,7 +462,7 @@ func Test_StorageErrorSafety(t *testing.T) {
priorLen := len(p.Keys)
err = p.Rotate(ctx, storage)
err = p.Rotate(ctx, storage, rand.Reader)
if err == nil {
t.Fatal("expected error")
}
@@ -480,7 +481,7 @@ func Test_BadUpgrade(t *testing.T) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -498,7 +499,7 @@ func Test_BadUpgrade(t *testing.T) {
p.Keys = nil
p.MinDecryptionVersion = 0
if err := p.Upgrade(ctx, storage); err != nil {
if err := p.Upgrade(ctx, storage, rand.Reader); err != nil {
t.Fatal(err)
}
@@ -521,7 +522,7 @@ func Test_BadUpgrade(t *testing.T) {
p.Keys = nil
p.MinDecryptionVersion = 0
if err := p.Upgrade(ctx, storage); err == nil {
if err := p.Upgrade(ctx, storage, rand.Reader); err == nil {
t.Fatal("expected error")
}
@@ -545,7 +546,7 @@ func Test_BadArchive(t *testing.T) {
Storage: storage,
KeyType: KeyType_AES256_GCM96,
Name: "test",
})
}, rand.Reader)
if err != nil {
t.Fatal(err)
}
@@ -554,7 +555,7 @@ func Test_BadArchive(t *testing.T) {
}
for i := 2; i <= 10; i++ {
err = p.Rotate(ctx, storage)
err = p.Rotate(ctx, storage, rand.Reader)
if err != nil {
t.Fatal(err)
}

View File

@@ -3,6 +3,7 @@ package vault
import (
"context"
"errors"
"io"
"time"
"github.com/hashicorp/vault/sdk/logical"
@@ -69,10 +70,10 @@ type SecurityBarrier interface {
// Initialize works only if the barrier has not been initialized
// and makes use of the given master key.
Initialize(context.Context, []byte) error
Initialize(context.Context, []byte, io.Reader) error
// GenerateKey is used to generate a new key
GenerateKey() ([]byte, error)
GenerateKey(io.Reader) ([]byte, error)
// KeyLength is used to sanity check a key
KeyLength() (int, int)
@@ -109,7 +110,7 @@ type SecurityBarrier interface {
// Rotate is used to create a new encryption key. All future writes
// should use the new key, while old values should still be decryptable.
Rotate(ctx context.Context) (uint32, error)
Rotate(ctx context.Context, reader io.Reader) (uint32, error)
// CreateUpgrade creates an upgrade path key to the given term from the previous term
CreateUpgrade(ctx context.Context, term uint32) error

View File

@@ -9,6 +9,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"io"
"strings"
"sync"
"time"
@@ -114,7 +115,7 @@ func (b *AESGCMBarrier) Initialized(ctx context.Context) (bool, error) {
// Initialize works only if the barrier has not been initialized
// and makes use of the given master key.
func (b *AESGCMBarrier) Initialize(ctx context.Context, key []byte) error {
func (b *AESGCMBarrier) Initialize(ctx context.Context, key []byte, reader io.Reader) error {
// Verify the key size
min, max := b.KeyLength()
if len(key) < min || len(key) > max {
@@ -129,7 +130,7 @@ func (b *AESGCMBarrier) Initialize(ctx context.Context, key []byte) error {
}
// Generate encryption key
encrypt, err := b.GenerateKey()
encrypt, err := b.GenerateKey(reader)
if err != nil {
return errwrap.Wrapf("failed to generate encryption key: {{err}}", err)
}
@@ -214,10 +215,11 @@ func (b *AESGCMBarrier) persistKeyring(ctx context.Context, keyring *Keyring) er
}
// GenerateKey is used to generate a new key
func (b *AESGCMBarrier) GenerateKey() ([]byte, error) {
func (b *AESGCMBarrier) GenerateKey(reader io.Reader) ([]byte, error) {
// Generate a 256bit key
buf := make([]byte, 2*aes.BlockSize)
_, err := rand.Read(buf)
_, err := reader.Read(buf)
return buf, err
}
@@ -478,7 +480,7 @@ func (b *AESGCMBarrier) Seal() error {
// Rotate is used to create a new encryption key. All future writes
// should use the new key, while old values should still be decryptable.
func (b *AESGCMBarrier) Rotate(ctx context.Context) (uint32, error) {
func (b *AESGCMBarrier) Rotate(ctx context.Context, reader io.Reader) (uint32, error) {
b.l.Lock()
defer b.l.Unlock()
if b.sealed {
@@ -486,7 +488,7 @@ func (b *AESGCMBarrier) Rotate(ctx context.Context) (uint32, error) {
}
// Generate a new key
encrypt, err := b.GenerateKey()
encrypt, err := b.GenerateKey(reader)
if err != nil {
return 0, errwrap.Wrapf("failed to generate encryption key: {{err}}", err)
}

View File

@@ -3,6 +3,7 @@ package vault
import (
"bytes"
"context"
"crypto/rand"
"encoding/json"
"testing"
@@ -29,8 +30,8 @@ func mockBarrier(t testing.TB) (physical.Backend, SecurityBarrier, []byte) {
}
// Initialize and unseal
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
return inm, b, key
}
@@ -116,7 +117,7 @@ func TestAESGCMBarrier_BackwardsCompatible(t *testing.T) {
}
// Generate a barrier/init entry
encrypt, _ := b.GenerateKey()
encrypt, _ := b.GenerateKey(rand.Reader)
init := &barrierInit{
Version: 1,
Key: encrypt,
@@ -124,7 +125,7 @@ func TestAESGCMBarrier_BackwardsCompatible(t *testing.T) {
buf, _ := json.Marshal(init)
// Protect with master key
master, _ := b.GenerateKey()
master, _ := b.GenerateKey(rand.Reader)
gcm, _ := b.aeadFromKey(master)
value, err := b.encrypt(barrierInitPath, initialKeyTerm, gcm, buf)
if err != nil {
@@ -205,8 +206,8 @@ func TestAESGCMBarrier_Confidential(t *testing.T) {
}
// Initialize and unseal
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
// Put a logical entry
@@ -245,8 +246,8 @@ func TestAESGCMBarrier_Integrity(t *testing.T) {
}
// Initialize and unseal
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
// Put a logical entry
@@ -284,8 +285,8 @@ func TestAESGCMBarrier_MoveIntegrityV1(t *testing.T) {
b.currentAESGCMVersionByte = AESGCMVersion1
// Initialize and unseal
key, _ := b.GenerateKey()
err = b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
err = b.Initialize(context.Background(), key, rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -328,8 +329,8 @@ func TestAESGCMBarrier_MoveIntegrityV2(t *testing.T) {
b.currentAESGCMVersionByte = AESGCMVersion2
// Initialize and unseal
key, _ := b.GenerateKey()
err = b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
err = b.Initialize(context.Background(), key, rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -372,8 +373,8 @@ func TestAESGCMBarrier_UpgradeV1toV2(t *testing.T) {
b.currentAESGCMVersionByte = AESGCMVersion1
// Initialize and unseal
key, _ := b.GenerateKey()
err = b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
err = b.Initialize(context.Background(), key, rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -425,8 +426,8 @@ func TestEncrypt_Unique(t *testing.T) {
t.Fatalf("err: %v", err)
}
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
if b.keyring == nil {
@@ -465,19 +466,19 @@ func TestInitialize_KeyLength(t *testing.T) {
middle := []byte("ThisIsASecretKeyAndMore")
short := []byte("Key")
err = b.Initialize(context.Background(), long)
err = b.Initialize(context.Background(), long, rand.Reader)
if err == nil {
t.Fatalf("key length protection failed")
}
err = b.Initialize(context.Background(), middle)
err = b.Initialize(context.Background(), middle, rand.Reader)
if err == nil {
t.Fatalf("key length protection failed")
}
err = b.Initialize(context.Background(), short)
err = b.Initialize(context.Background(), short, rand.Reader)
if err == nil {
t.Fatalf("key length protection failed")
@@ -498,8 +499,8 @@ func TestEncrypt_BarrierEncryptor(t *testing.T) {
}
// Initialize and unseal
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
cipher, err := b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
@@ -528,8 +529,8 @@ func TestAESGCMBarrier_ReloadKeyring(t *testing.T) {
}
// Initialize and unseal
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
b.Unseal(context.Background(), key)
keyringRaw, err := inm.Get(context.Background(), keyringPath)
@@ -550,7 +551,7 @@ func TestAESGCMBarrier_ReloadKeyring(t *testing.T) {
t.Fatalf("err: %v", err)
}
b2.Unseal(context.Background(), key)
_, err = b2.Rotate(context.Background())
_, err = b2.Rotate(context.Background(), rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}

View File

@@ -2,6 +2,7 @@ package vault
import (
"context"
"crypto/rand"
"reflect"
"testing"
"time"
@@ -49,7 +50,7 @@ func testBarrier(t *testing.T, b SecurityBarrier) {
}
// Get a new key
key, err := b.GenerateKey()
key, err := b.GenerateKey(rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -69,12 +70,12 @@ func testBarrier(t *testing.T, b SecurityBarrier) {
}
// Initialize the vault
if err := b.Initialize(context.Background(), key); err != nil {
if err := b.Initialize(context.Background(), key, rand.Reader); err != nil {
t.Fatalf("err: %v", err)
}
// Double Initialize should fail
if err := b.Initialize(context.Background(), key); err != ErrBarrierAlreadyInit {
if err := b.Initialize(context.Background(), key, rand.Reader); err != ErrBarrierAlreadyInit {
t.Fatalf("err: %v", err)
}
@@ -245,8 +246,8 @@ func testBarrier(t *testing.T, b SecurityBarrier) {
func testBarrier_Rotate(t *testing.T, b SecurityBarrier) {
// Initialize the barrier
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
err := b.Unseal(context.Background(), key)
if err != nil {
t.Fatalf("err: %v", err)
@@ -272,7 +273,7 @@ func testBarrier_Rotate(t *testing.T, b SecurityBarrier) {
}
// Rotate the encryption key
newTerm, err := b.Rotate(context.Background())
newTerm, err := b.Rotate(context.Background(), rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -351,8 +352,8 @@ func testBarrier_Rotate(t *testing.T, b SecurityBarrier) {
func testBarrier_Rekey(t *testing.T, b SecurityBarrier) {
// Initialize the barrier
key, _ := b.GenerateKey()
b.Initialize(context.Background(), key)
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, rand.Reader)
err := b.Unseal(context.Background(), key)
if err != nil {
t.Fatalf("err: %v", err)
@@ -370,7 +371,7 @@ func testBarrier_Rekey(t *testing.T, b SecurityBarrier) {
}
// Rekey to a new key
newKey, _ := b.GenerateKey()
newKey, _ := b.GenerateKey(rand.Reader)
err = b.Rekey(context.Background(), newKey)
if err != nil {
t.Fatalf("err: %v", err)
@@ -431,8 +432,8 @@ func testBarrier_Rekey(t *testing.T, b SecurityBarrier) {
func testBarrier_Upgrade(t *testing.T, b1, b2 SecurityBarrier) {
// Initialize the barrier
key, _ := b1.GenerateKey()
b1.Initialize(context.Background(), key)
key, _ := b1.GenerateKey(rand.Reader)
b1.Initialize(context.Background(), key, rand.Reader)
err := b1.Unseal(context.Background(), key)
if err != nil {
t.Fatalf("err: %v", err)
@@ -443,7 +444,7 @@ func testBarrier_Upgrade(t *testing.T, b1, b2 SecurityBarrier) {
}
// Rotate the encryption key
newTerm, err := b1.Rotate(context.Background())
newTerm, err := b1.Rotate(context.Background(), rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -473,7 +474,7 @@ func testBarrier_Upgrade(t *testing.T, b1, b2 SecurityBarrier) {
}
// Rotate the encryption key
newTerm, err = b1.Rotate(context.Background())
newTerm, err = b1.Rotate(context.Background(), rand.Reader)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -502,8 +503,8 @@ func testBarrier_Upgrade(t *testing.T, b1, b2 SecurityBarrier) {
func testBarrier_Upgrade_Rekey(t *testing.T, b1, b2 SecurityBarrier) {
// Initialize the barrier
key, _ := b1.GenerateKey()
b1.Initialize(context.Background(), key)
key, _ := b1.GenerateKey(rand.Reader)
b1.Initialize(context.Background(), key, rand.Reader)
err := b1.Unseal(context.Background(), key)
if err != nil {
t.Fatalf("err: %v", err)
@@ -514,7 +515,7 @@ func testBarrier_Upgrade_Rekey(t *testing.T, b1, b2 SecurityBarrier) {
}
// Rekey to a new key
newKey, _ := b1.GenerateKey()
newKey, _ := b1.GenerateKey(rand.Reader)
err = b1.Rekey(context.Background(), newKey)
if err != nil {
t.Fatalf("err: %v", err)

View File

@@ -205,7 +205,7 @@ func (c *Core) setupCluster(ctx context.Context) error {
// Create a private key
if c.localClusterPrivateKey.Load().(*ecdsa.PrivateKey) == nil {
c.logger.Debug("generating cluster private key")
key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
key, err := ecdsa.GenerateKey(elliptic.P521(), c.secureRandomReader)
if err != nil {
c.logger.Error("failed to generate local cluster key", "error", err)
return err

View File

@@ -3,11 +3,13 @@ package vault
import (
"context"
"crypto/ecdsa"
"crypto/rand"
"crypto/subtle"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
@@ -471,6 +473,9 @@ type Core struct {
coreNumber int
// secureRandomReader is the reader used for CSP operations
secureRandomReader io.Reader
recoveryMode bool
}
@@ -495,6 +500,8 @@ type CoreConfig struct {
Seal Seal `json:"seal" structs:"seal" mapstructure:"seal"`
SecureRandomReader io.Reader `json:"secure_random_reader" structs:"secure_random_reader" mapstructure:"secure_random_reader"`
Logger log.Logger `json:"logger" structs:"logger" mapstructure:"logger"`
// Disables the LRU cache on the physical backend
@@ -633,6 +640,11 @@ func NewCore(conf *CoreConfig) (*Core, error) {
syncInterval = 30 * time.Second
}
// secureRandomReader cannot be nil
if conf.SecureRandomReader == nil {
conf.SecureRandomReader = rand.Reader
}
// Setup the core
c := &Core{
entCore: entCore{},
@@ -673,6 +685,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
neverBecomeActive: new(uint32),
clusterLeaderParams: new(atomic.Value),
metricsHelper: conf.MetricsHelper,
secureRandomReader: conf.SecureRandomReader,
rawConfig: conf.RawConfig,
counters: counters{
requests: new(uint64),
@@ -1152,7 +1165,7 @@ func (c *Core) unsealPart(ctx context.Context, seal Seal, key []byte, useRecover
}
// Generate a new master key
newMasterKey, err := c.barrier.GenerateKey()
newMasterKey, err := c.barrier.GenerateKey(c.secureRandomReader)
if err != nil {
return nil, errwrap.Wrapf("error generating new master key: {{err}}", err)
}

View File

@@ -90,7 +90,7 @@ func (c *Core) Initialized(ctx context.Context) (bool, error) {
func (c *Core) generateShares(sc *SealConfig) ([]byte, [][]byte, error) {
// Generate a master key
masterKey, err := c.barrier.GenerateKey()
masterKey, err := c.barrier.GenerateKey(c.secureRandomReader)
if err != nil {
return nil, nil, errwrap.Wrapf("key generation failed: {{err}}", err)
}
@@ -213,7 +213,7 @@ func (c *Core) Initialize(ctx context.Context, initParams *InitParams) (*InitRes
}
// Initialize the barrier
if err := c.barrier.Initialize(ctx, barrierKey); err != nil {
if err := c.barrier.Initialize(ctx, barrierKey, c.secureRandomReader); err != nil {
c.logger.Error("failed to initialize barrier", "error", err)
return nil, errwrap.Wrapf("failed to initialize barrier: {{err}}", err)
}

View File

@@ -665,6 +665,7 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
"accessor": entry.Accessor,
"local": entry.Local,
"seal_wrap": entry.SealWrap,
"external_entropy_access": entry.ExternalEntropyAccess,
"options": entry.Options,
"uuid": entry.UUID,
}
@@ -755,6 +756,7 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
description := data.Get("description").(string)
pluginName := data.Get("plugin_name").(string)
sealWrap := data.Get("seal_wrap").(bool)
externalEntropyAccess := data.Get("external_entropy_access").(bool)
options := data.Get("options").(map[string]string)
var config MountConfig
@@ -886,6 +888,7 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
Config: config,
Local: local,
SealWrap: sealWrap,
ExternalEntropyAccess: externalEntropyAccess,
Options: options,
}
@@ -1055,6 +1058,11 @@ func (b *SystemBackend) handleTuneReadCommon(ctx context.Context, path string) (
},
}
// not tunable so doesn't need to be stored/loaded through synthesizedConfigCache
if mountEntry.ExternalEntropyAccess {
resp.Data["external_entropy_access"] = true
}
if mountEntry.Table == credentialTableType {
resp.Data["token_type"] = mountEntry.Config.TokenType.String()
}
@@ -1688,6 +1696,7 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
description := data.Get("description").(string)
pluginName := data.Get("plugin_name").(string)
sealWrap := data.Get("seal_wrap").(bool)
externalEntropyAccess := data.Get("external_entropy_access").(bool)
options := data.Get("options").(map[string]string)
var config MountConfig
@@ -1808,6 +1817,7 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
Config: config,
Local: local,
SealWrap: sealWrap,
ExternalEntropyAccess: externalEntropyAccess,
Options: options,
}
@@ -2240,7 +2250,7 @@ func (b *SystemBackend) handleRotate(ctx context.Context, req *logical.Request,
}
// Rotate to the new term
newTerm, err := b.Core.barrier.Rotate(ctx)
newTerm, err := b.Core.barrier.Rotate(ctx, b.Core.secureRandomReader)
if err != nil {
b.Backend.Logger().Error("failed to create new encryption key", "error", err)
return handleError(err)
@@ -3503,6 +3513,10 @@ in the plugin catalog.`,
`Whether to turn on seal wrapping for the mount.`,
},
"external_entropy_access": {
`Whether to give the mount access to Vault's external entropy.`,
},
"tune_default_lease_ttl": {
`The default lease TTL for this mount.`,
},

View File

@@ -1316,6 +1316,11 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"external_entropy_access": &framework.FieldSchema{
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"plugin_name": &framework.FieldSchema{
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_plugin"][0]),
@@ -1606,6 +1611,11 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"external_entropy_access": &framework.FieldSchema{
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"plugin_name": &framework.FieldSchema{
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_plugin_name"][0]),

View File

@@ -151,6 +151,7 @@ func TestSystemBackend_mounts(t *testing.T) {
exp := map[string]interface{}{
"secret/": map[string]interface{}{
"type": "kv",
"external_entropy_access": false,
"description": "key/value secret storage",
"accessor": resp.Data["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret/"].(map[string]interface{})["uuid"],
@@ -167,6 +168,7 @@ func TestSystemBackend_mounts(t *testing.T) {
},
"sys/": map[string]interface{}{
"type": "system",
"external_entropy_access": false,
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["sys/"].(map[string]interface{})["uuid"],
@@ -183,6 +185,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"accessor": resp.Data["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -197,6 +200,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"accessor": resp.Data["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -248,6 +252,7 @@ func TestSystemBackend_mount(t *testing.T) {
exp := map[string]interface{}{
"secret/": map[string]interface{}{
"type": "kv",
"external_entropy_access": false,
"description": "key/value secret storage",
"accessor": resp.Data["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret/"].(map[string]interface{})["uuid"],
@@ -264,6 +269,7 @@ func TestSystemBackend_mount(t *testing.T) {
},
"sys/": map[string]interface{}{
"type": "system",
"external_entropy_access": false,
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["sys/"].(map[string]interface{})["uuid"],
@@ -280,6 +286,7 @@ func TestSystemBackend_mount(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"accessor": resp.Data["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -294,6 +301,7 @@ func TestSystemBackend_mount(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"accessor": resp.Data["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -308,6 +316,7 @@ func TestSystemBackend_mount(t *testing.T) {
"prod/secret/": map[string]interface{}{
"description": "",
"type": "kv",
"external_entropy_access": false,
"accessor": resp.Data["prod/secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["prod/secret/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -1448,6 +1457,7 @@ func TestSystemBackend_authTable(t *testing.T) {
exp := map[string]interface{}{
"token/": map[string]interface{}{
"type": "token",
"external_entropy_access": false,
"description": "token based credentials",
"accessor": resp.Data["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["token/"].(map[string]interface{})["uuid"],
@@ -1502,6 +1512,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
exp := map[string]interface{}{
"foo/": map[string]interface{}{
"type": "noop",
"external_entropy_access": false,
"description": "",
"accessor": resp.Data["foo/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["foo/"].(map[string]interface{})["uuid"],
@@ -1517,6 +1528,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
},
"token/": map[string]interface{}{
"type": "token",
"external_entropy_access": false,
"description": "token based credentials",
"accessor": resp.Data["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["token/"].(map[string]interface{})["uuid"],
@@ -2285,6 +2297,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"secret": map[string]interface{}{
"secret/": map[string]interface{}{
"type": "kv",
"external_entropy_access": false,
"description": "key/value secret storage",
"accessor": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["uuid"],
@@ -2301,6 +2314,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
},
"sys/": map[string]interface{}{
"type": "system",
"external_entropy_access": false,
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["uuid"],
@@ -2317,6 +2331,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"cubbyhole/": map[string]interface{}{
"description": "per-token private secret storage",
"type": "cubbyhole",
"external_entropy_access": false,
"accessor": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -2331,6 +2346,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"identity/": map[string]interface{}{
"description": "identity store",
"type": "identity",
"external_entropy_access": false,
"accessor": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
@@ -2353,6 +2369,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"token_type": "default-service",
},
"type": "token",
"external_entropy_access": false,
"description": "token based credentials",
"accessor": resp.Data["auth"].(map[string]interface{})["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["auth"].(map[string]interface{})["token/"].(map[string]interface{})["uuid"],

View File

@@ -220,6 +220,7 @@ type MountEntry struct {
Options map[string]string `json:"options"` // Backend options
Local bool `json:"local"` // Local mounts are not replicated or affected by replication
SealWrap bool `json:"seal_wrap"` // Whether to wrap CSPs
ExternalEntropyAccess bool `json:"external_entropy_access"` // Whether to allow external entropy source access
Tainted bool `json:"tainted,omitempty"` // Set as a Write-Ahead flag for unmount/remount
NamespaceID string `json:"namespace_id"`
@@ -1249,18 +1250,6 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
return b, nil
}
// mountEntrySysView creates a logical.SystemView from global and
// mount-specific entries; because this should be called when setting
// up a mountEntry, it doesn't check to ensure that me is not nil
func (c *Core) mountEntrySysView(entry *MountEntry) extendedSystemView {
return extendedSystemViewImpl{
dynamicSystemView{
core: c,
mountEntry: entry,
},
}
}
// defaultMountTable creates a default mount table
func (c *Core) defaultMountTable() *MountTable {
table := &MountTable{

View File

@@ -41,3 +41,15 @@ func (e *MountEntry) ViewPath() string {
}
func verifyNamespace(*Core, *namespace.Namespace, *MountEntry) error { return nil }
// mountEntrySysView creates a logical.SystemView from global and
// mount-specific entries; because this should be called when setting
// up a mountEntry, it doesn't check to ensure that me is not nil
func (c *Core) mountEntrySysView(entry *MountEntry) extendedSystemView {
return extendedSystemViewImpl{
dynamicSystemView{
core: c,
mountEntry: entry,
},
}
}

View File

@@ -105,7 +105,7 @@ func (c *Core) startRaftStorage(ctx context.Context) (retErr error) {
// this state the unseal will fail and a cluster recovery will need to
// be done.
creating = true
raftTLSKey, err := raft.GenerateTLSKey()
raftTLSKey, err := raft.GenerateTLSKey(c.secureRandomReader)
if err != nil {
return err
}
@@ -267,7 +267,7 @@ func (c *Core) startPeriodicRaftTLSRotate(ctx context.Context) error {
logger.Info("creating new raft TLS config")
// Create a new key
raftTLSKey, err := raft.GenerateTLSKey()
raftTLSKey, err := raft.GenerateTLSKey(c.secureRandomReader)
if err != nil {
return time.Time{}, errwrap.Wrapf("failed to generate new raft TLS key: {{err}}", err)
}
@@ -399,7 +399,7 @@ func (c *Core) createRaftTLSKeyring(ctx context.Context) error {
return nil
}
raftTLS, err := raft.GenerateTLSKey()
raftTLS, err := raft.GenerateTLSKey(c.secureRandomReader)
if err != nil {
return err
}

View File

@@ -397,7 +397,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
}
// Generate a new master key
newMasterKey, err := c.barrier.GenerateKey()
newMasterKey, err := c.barrier.GenerateKey(c.secureRandomReader)
if err != nil {
c.logger.Error("failed to generate master key", "error", err)
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("master key generation failed: {{err}}", err).Error())
@@ -629,7 +629,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
}
// Generate a new master key
newMasterKey, err := c.barrier.GenerateKey()
newMasterKey, err := c.barrier.GenerateKey(c.secureRandomReader)
if err != nil {
c.logger.Error("failed to generate recovery key", "error", err)
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("recovery key generation failed: {{err}}", err).Error())

View File

@@ -22,7 +22,7 @@ const (
HSMAutoDeprecated = "hsm-auto"
)
// Access is the embedded implemention of autoSeal that contains logic
// Access is the embedded implementation of autoSeal that contains logic
// specific to encrypting and decrypting data, or in this case keys.
type Access interface {
SealType() string

View File

@@ -1368,6 +1368,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
coreConfig.LicensingConfig = base.LicensingConfig
coreConfig.DisablePerformanceStandby = base.DisablePerformanceStandby
coreConfig.MetricsHelper = base.MetricsHelper
coreConfig.SecureRandomReader = base.SecureRandomReader
if base.BuiltinRegistry != nil {
coreConfig.BuiltinRegistry = base.BuiltinRegistry
}

View File

@@ -785,7 +785,7 @@ func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) err
if entry.ID == "" {
userSelectedID = false
var err error
entry.ID, err = base62.Random(TokenLength)
entry.ID, err = base62.RandomWithReader(TokenLength, ts.core.secureRandomReader)
if err != nil {
return err
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
@@ -17,7 +16,7 @@ import (
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/logical"
jose "gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2"
squarejwt "gopkg.in/square/go-jose.v2/jwt"
)
@@ -35,7 +34,7 @@ func (c *Core) ensureWrappingKey(ctx context.Context) error {
var keyParams certutil.ClusterKeyParams
if entry == nil {
key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
key, err := ecdsa.GenerateKey(elliptic.P521(), c.secureRandomReader)
if err != nil {
return errwrap.Wrapf("failed to generate wrapping key: {{err}}", err)
}

1
vendor/github.com/boombuler/barcode/go.mod generated vendored Normal file
View File

@@ -0,0 +1 @@
module github.com/boombuler/barcode

View File

@@ -46,7 +46,7 @@ func (c *base1DCodeIntCS) CheckSum() int {
return c.checksum
}
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
// New1DCodeIntCheckSum creates a new 1D barcode where the bars are represented by the bits in the bars BitList
func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS {
return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum}
}

View File

@@ -4,22 +4,40 @@ import (
"crypto/rand"
"encoding/hex"
"fmt"
"io"
)
// GenerateRandomBytes is used to generate random bytes of given size.
func GenerateRandomBytes(size int) ([]byte, error) {
return GenerateRandomBytesWithReader(size, rand.Reader)
}
// GenerateRandomBytesWithReader is used to generate random bytes of given size read from a given reader.
func GenerateRandomBytesWithReader(size int, reader io.Reader) ([]byte, error) {
if reader == nil {
return nil, fmt.Errorf("provided reader is nil")
}
buf := make([]byte, size)
if _, err := rand.Read(buf); err != nil {
if _, err := io.ReadFull(reader, buf); err != nil {
return nil, fmt.Errorf("failed to read random bytes: %v", err)
}
return buf, nil
}
const uuidLen = 16
// GenerateUUID is used to generate a random UUID
func GenerateUUID() (string, error) {
buf, err := GenerateRandomBytes(uuidLen)
return GenerateUUIDWithReader(rand.Reader)
}
// GenerateUUIDWithReader is used to generate a random UUID with a given Reader
func GenerateUUIDWithReader(reader io.Reader) (string, error) {
if reader == nil {
return "", fmt.Errorf("provided reader is nil")
}
buf, err := GenerateRandomBytesWithReader(uuidLen, reader)
if err != nil {
return "", err
}

View File

@@ -270,7 +270,7 @@ func (b *versionedKVBackend) policy(ctx context.Context, s logical.Storage) (*ke
VersionTemplate: keysutil.EncryptedKeyPolicyVersionTpl,
})
err = policy.Rotate(ctx, s)
err = policy.Rotate(ctx, s, b.GetRandomReader())
if err != nil {
return nil, err
}

View File

@@ -38,6 +38,7 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=

View File

@@ -10,6 +10,10 @@ func (c *Sys) GenerateDROperationTokenStatus() (*GenerateRootStatusResponse, err
return c.generateRootStatusCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt")
}
func (c *Sys) GenerateRecoveryOperationTokenStatus() (*GenerateRootStatusResponse, error) {
return c.generateRootStatusCommon("/v1/sys/generate-recovery-token/attempt")
}
func (c *Sys) generateRootStatusCommon(path string) (*GenerateRootStatusResponse, error) {
r := c.c.NewRequest("GET", path)
@@ -34,6 +38,10 @@ func (c *Sys) GenerateDROperationTokenInit(otp, pgpKey string) (*GenerateRootSta
return c.generateRootInitCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt", otp, pgpKey)
}
func (c *Sys) GenerateRecoveryOperationTokenInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
return c.generateRootInitCommon("/v1/sys/generate-recovery-token/attempt", otp, pgpKey)
}
func (c *Sys) generateRootInitCommon(path, otp, pgpKey string) (*GenerateRootStatusResponse, error) {
body := map[string]interface{}{
"otp": otp,
@@ -66,6 +74,10 @@ func (c *Sys) GenerateDROperationTokenCancel() error {
return c.generateRootCancelCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt")
}
func (c *Sys) GenerateRecoveryOperationTokenCancel() error {
return c.generateRootCancelCommon("/v1/sys/generate-recovery-token/attempt")
}
func (c *Sys) generateRootCancelCommon(path string) error {
r := c.c.NewRequest("DELETE", path)
@@ -86,6 +98,10 @@ func (c *Sys) GenerateDROperationTokenUpdate(shard, nonce string) (*GenerateRoot
return c.generateRootUpdateCommon("/v1/sys/replication/dr/secondary/generate-operation-token/update", shard, nonce)
}
func (c *Sys) GenerateRecoveryOperationTokenUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
return c.generateRootUpdateCommon("/v1/sys/generate-recovery-token/update", shard, nonce)
}
func (c *Sys) generateRootUpdateCommon(path, shard, nonce string) (*GenerateRootStatusResponse, error) {
body := map[string]interface{}{
"key": shard,

View File

@@ -134,6 +134,7 @@ type MountInput struct {
Config MountConfigInput `json:"config"`
Local bool `json:"local"`
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
Options map[string]string `json:"options"`
// Deprecated: Newer server responses should be returning this information in the
@@ -167,6 +168,7 @@ type MountOutput struct {
Options map[string]string `json:"options"`
Local bool `json:"local"`
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
}
type MountConfigOutput struct {

View File

@@ -2,7 +2,9 @@ package framework
import (
"context"
"crypto/rand"
"fmt"
"io"
"io/ioutil"
"net/http"
"regexp"
@@ -14,6 +16,7 @@ import (
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/helper/entropy"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/helper/license"
"github.com/hashicorp/vault/sdk/helper/logging"
@@ -279,6 +282,17 @@ func (b *Backend) Setup(ctx context.Context, config *logical.BackendConfig) erro
return nil
}
// GetRandomReader returns an io.Reader to use for generating key material in
// backends. If the backend has access to an external entropy source it will
// return that, otherwise it returns crypto/rand.Reader.
func (b *Backend) GetRandomReader() io.Reader {
if sourcer, ok := b.System().(entropy.Sourcer); ok {
return entropy.NewReader(sourcer)
}
return rand.Reader
}
// Logger can be used to get the logger. If no logger has been set,
// the logs will be discarded.
func (b *Backend) Logger() log.Logger {

View File

@@ -3,7 +3,9 @@
package base62
import (
"crypto/rand"
uuid "github.com/hashicorp/go-uuid"
"io"
)
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
@@ -12,6 +14,12 @@ const csLen = byte(len(charset))
// Random generates a random string using base-62 characters.
// Resulting entropy is ~5.95 bits/character.
func Random(length int) (string, error) {
return RandomWithReader(length, rand.Reader)
}
// RandomWithReader generates a random string using base-62 characters and a given reader.
// Resulting entropy is ~5.95 bits/character.
func RandomWithReader(length int, reader io.Reader) (string, error) {
if length == 0 {
return "", nil
}
@@ -22,7 +30,7 @@ func Random(length int) (string, error) {
batchSize := length + length/4
for {
buf, err := uuid.GenerateRandomBytes(batchSize)
buf, err := uuid.GenerateRandomBytesWithReader(batchSize, reader)
if err != nil {
return "", err
}

View File

@@ -0,0 +1,36 @@
package entropy
import (
"fmt"
"github.com/hashicorp/errwrap"
)
type Sourcer interface {
GetRandom(bytes int) ([]byte, error)
}
type Reader struct {
source Sourcer
}
func NewReader(source Sourcer) *Reader{
return &Reader{source}
}
// Read reads exactly len(p) bytes from r into p.
// If r returns an error having read at least len(p) bytes, the error is dropped.
// It returns the number of bytes copied and an error if fewer bytes were read.
// On return, n == len(p) if and only if err == nil.
func (r *Reader) Read(p []byte) (n int, err error){
requested := len(p)
randBytes, err := r.source.GetRandom(requested)
delivered := copy(p, randBytes)
if delivered != requested {
if err != nil {
return delivered, errwrap.Wrapf("unable to fill provided buffer with entropy: {{err}}", err)
}
return delivered, fmt.Errorf("unable to fill provided buffer with entropy")
}
return delivered, nil
}

View File

@@ -5,6 +5,7 @@ import (
"encoding/base64"
"errors"
"fmt"
"io"
"sync"
"sync/atomic"
"time"
@@ -249,7 +250,7 @@ func (lm *LockManager) BackupPolicy(ctx context.Context, storage logical.Storage
// When the function returns, if caching was disabled, the Policy's lock must
// be unlocked when the caller is done (and it should not be re-locked).
func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *Policy, retUpserted bool, retErr error) {
func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest, rand io.Reader) (retP *Policy, retUpserted bool, retErr error) {
var p *Policy
var err error
var ok bool
@@ -379,7 +380,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
}
// Performs the actual persist and does setup
err = p.Rotate(ctx, req.Storage)
err = p.Rotate(ctx, req.Storage, rand)
if err != nil {
cleanup()
return nil, false, err
@@ -400,7 +401,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
}
if p.NeedsUpgrade() {
if err := p.Upgrade(ctx, req.Storage); err != nil {
if err := p.Upgrade(ctx, req.Storage, rand); err != nil {
cleanup()
return nil, false, err
}

View File

@@ -613,7 +613,7 @@ func (p *Policy) NeedsUpgrade() bool {
return false
}
func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage) (retErr error) {
func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage, randReader io.Reader) (retErr error) {
priorKey := p.Key
priorLatestVersion := p.LatestVersion
priorMinDecryptionVersion := p.MinDecryptionVersion
@@ -670,7 +670,7 @@ func (p *Policy) Upgrade(ctx context.Context, storage logical.Storage) (retErr e
if p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey == nil || len(p.Keys[strconv.Itoa(p.LatestVersion)].HMACKey) == 0 {
entry := p.Keys[strconv.Itoa(p.LatestVersion)]
hmacKey, err := uuid.GenerateRandomBytes(32)
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
if err != nil {
return err
}
@@ -1371,7 +1371,7 @@ func (p *Policy) VerifySignature(context, input []byte, hashAlgorithm HashType,
}
}
func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr error) {
func (p *Policy) Rotate(ctx context.Context, storage logical.Storage, randReader io.Reader) (retErr error) {
priorLatestVersion := p.LatestVersion
priorMinDecryptionVersion := p.MinDecryptionVersion
var priorKeys keyEntryMap
@@ -1405,7 +1405,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
DeprecatedCreationTime: now.Unix(),
}
hmacKey, err := uuid.GenerateRandomBytes(32)
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
if err != nil {
return err
}
@@ -1418,7 +1418,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
if p.Type == KeyType_AES128_GCM96 {
numBytes = 16
}
newKey, err := uuid.GenerateRandomBytes(numBytes)
newKey, err := uuid.GenerateRandomBytesWithReader(numBytes, randReader)
if err != nil {
return err
}
@@ -1457,7 +1457,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
entry.FormattedPublicKey = string(pemBytes)
case KeyType_ED25519:
pub, pri, err := ed25519.GenerateKey(rand.Reader)
pub, pri, err := ed25519.GenerateKey(randReader)
if err != nil {
return err
}
@@ -1470,7 +1470,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
bitSize = 4096
}
entry.RSAKey, err = rsa.GenerateKey(rand.Reader, bitSize)
entry.RSAKey, err = rsa.GenerateKey(randReader, bitSize)
if err != nil {
return err
}

View File

@@ -1,7 +1,7 @@
language: go
env:
- GO111MODULE=on
go:
- "1.8"
- "1.9"
- "1.10"
- "tip"
- "1.12"

8
vendor/github.com/pquerna/otp/go.mod generated vendored Normal file
View File

@@ -0,0 +1,8 @@
module github.com/pquerna/otp
go 1.12
require (
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/stretchr/testify v1.3.0
)

11
vendor/github.com/pquerna/otp/go.sum generated vendored Normal file
View File

@@ -0,0 +1,11 @@
github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@@ -19,6 +19,7 @@ package hotp
import (
"github.com/pquerna/otp"
"io"
"crypto/hmac"
"crypto/rand"
@@ -146,12 +147,18 @@ type GenerateOpts struct {
AccountName string
// Size in size of the generated Secret. Defaults to 10 bytes.
SecretSize uint
// Secret to store. Defaults to a randomly generated secret of SecretSize. You should generally leave this empty.
Secret []byte
// Digits to request. Defaults to 6.
Digits otp.Digits
// Algorithm to use for HMAC. Defaults to SHA1.
Algorithm otp.Algorithm
// Reader to use for generating HOTP Key.
Rand io.Reader
}
var b32NoPadding = base32.StdEncoding.WithPadding(base32.NoPadding)
// Generate creates a new HOTP Key.
func Generate(opts GenerateOpts) (*otp.Key, error) {
// url encode the Issuer/AccountName
@@ -171,16 +178,24 @@ func Generate(opts GenerateOpts) (*otp.Key, error) {
opts.Digits = otp.DigitsSix
}
if opts.Rand == nil {
opts.Rand = rand.Reader
}
// otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
v := url.Values{}
if len(opts.Secret) != 0 {
v.Set("secret", b32NoPadding.EncodeToString(opts.Secret))
} else {
secret := make([]byte, opts.SecretSize)
_, err := rand.Read(secret)
_, err := opts.Rand.Read(secret)
if err != nil {
return nil, err
}
v.Set("secret", b32NoPadding.EncodeToString(secret))
}
v.Set("secret", strings.TrimRight(base32.StdEncoding.EncodeToString(secret), "="))
v.Set("issuer", opts.Issuer)
v.Set("algorithm", opts.Algorithm.String())
v.Set("digits", opts.Digits.String())

View File

@@ -18,10 +18,9 @@
package totp
import (
"strings"
"github.com/pquerna/otp"
"github.com/pquerna/otp/hotp"
"io"
"crypto/rand"
"encoding/base32"
@@ -138,12 +137,18 @@ type GenerateOpts struct {
Period uint
// Size in size of the generated Secret. Defaults to 20 bytes.
SecretSize uint
// Secret to store. Defaults to a randomly generated secret of SecretSize. You should generally leave this empty.
Secret []byte
// Digits to request. Defaults to 6.
Digits otp.Digits
// Algorithm to use for HMAC. Defaults to SHA1.
Algorithm otp.Algorithm
// Reader to use for generating TOTP Key.
Rand io.Reader
}
var b32NoPadding = base32.StdEncoding.WithPadding(base32.NoPadding)
// Generate a new TOTP Key.
func Generate(opts GenerateOpts) (*otp.Key, error) {
// url encode the Issuer/AccountName
@@ -167,16 +172,24 @@ func Generate(opts GenerateOpts) (*otp.Key, error) {
opts.Digits = otp.DigitsSix
}
if opts.Rand == nil {
opts.Rand = rand.Reader
}
// otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
v := url.Values{}
if len(opts.Secret) != 0 {
v.Set("secret", b32NoPadding.EncodeToString(opts.Secret))
} else {
secret := make([]byte, opts.SecretSize)
_, err := rand.Read(secret)
_, err := opts.Rand.Read(secret)
if err != nil {
return nil, err
}
v.Set("secret", b32NoPadding.EncodeToString(secret))
}
v.Set("secret", strings.TrimRight(base32.StdEncoding.EncodeToString(secret), "="))
v.Set("issuer", opts.Issuer)
v.Set("period", strconv.FormatUint(uint64(opts.Period), 10))
v.Set("algorithm", opts.Algorithm.String())

9
vendor/modules.txt vendored
View File

@@ -145,7 +145,7 @@ github.com/aws/aws-sdk-go/private/protocol/json/jsonutil
github.com/beorn7/perks/quantile
# github.com/bgentry/speakeasy v0.1.0
github.com/bgentry/speakeasy
# github.com/boombuler/barcode v1.0.0
# github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/boombuler/barcode
github.com/boombuler/barcode/qr
github.com/boombuler/barcode/utils
@@ -316,7 +316,7 @@ github.com/hashicorp/go-rootcerts
github.com/hashicorp/go-sockaddr
# github.com/hashicorp/go-syslog v1.0.0
github.com/hashicorp/go-syslog
# github.com/hashicorp/go-uuid v1.0.1
# github.com/hashicorp/go-uuid v1.0.2-0.20191001231223-f32f5fe8d6a8
github.com/hashicorp/go-uuid
# github.com/hashicorp/go-version v1.2.0
github.com/hashicorp/go-version
@@ -383,7 +383,7 @@ github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil
github.com/hashicorp/vault-plugin-secrets-gcp/plugin/util
# github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.2-0.20190814210149-315cdbf5de6e
github.com/hashicorp/vault-plugin-secrets-gcpkms
# github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190814210155-e060c2a001a8
# github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20191003164552-6600ec024c24
github.com/hashicorp/vault-plugin-secrets-kv
# github.com/hashicorp/vault/api v1.0.5-0.20190919134245-4eefe0ebe1a1 => ./api
github.com/hashicorp/vault/api
@@ -428,6 +428,7 @@ github.com/hashicorp/vault/sdk/plugin/pb
github.com/hashicorp/vault/sdk/database/helper/connutil
github.com/hashicorp/vault/sdk/helper/license
github.com/hashicorp/vault/sdk/helper/pluginutil
github.com/hashicorp/vault/sdk/helper/entropy
github.com/hashicorp/vault/sdk/helper/kdf
github.com/hashicorp/vault/sdk/plugin/mock
# github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
@@ -572,7 +573,7 @@ github.com/posener/complete/match
# github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35
github.com/pquerna/cachecontrol
github.com/pquerna/cachecontrol/cacheobject
# github.com/pquerna/otp v1.1.0
# github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d
github.com/pquerna/otp
github.com/pquerna/otp/totp
github.com/pquerna/otp/hotp