core: updates to password policy generator (#11596)
* core: fix bug in password policies not using namespaces * Add changelog
This commit is contained in:
parent
3f242a4432
commit
502cf3b212
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
core (enterprise): Fix plugins mounted in namespaces being unable to use password policies
|
||||
```
|
|
@ -336,11 +336,11 @@ func (d dynamicSystemView) GeneratePasswordFromPolicy(ctx context.Context, polic
|
|||
// Ensure there's a timeout on the context of some sort
|
||||
if _, hasTimeout := ctx.Deadline(); !hasTimeout {
|
||||
var cancel func()
|
||||
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
|
||||
ctx, cancel = context.WithTimeout(ctx, 1*time.Second)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
policyCfg, err := retrievePasswordPolicy(ctx, d.core.systemBarrierView, policyName)
|
||||
policyCfg, err := d.retrievePasswordPolicy(ctx, policyName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to retrieve password policy: %w", err)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package vault
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
@ -16,6 +16,22 @@ import (
|
|||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
var testPolicyName = "testpolicy"
|
||||
var rawTestPasswordPolicy = `
|
||||
length = 20
|
||||
rule "charset" {
|
||||
charset = "abcdefghijklmnopqrstuvwxyz"
|
||||
min_chars = 1
|
||||
}
|
||||
rule "charset" {
|
||||
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
min_chars = 1
|
||||
}
|
||||
rule "charset" {
|
||||
charset = "0123456789"
|
||||
min_chars = 1
|
||||
}`
|
||||
|
||||
func TestIdentity_BackendTemplating(t *testing.T) {
|
||||
var err error
|
||||
coreConfig := &CoreConfig{
|
||||
|
@ -157,47 +173,45 @@ func TestIdentity_BackendTemplating(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDynamicSystemView_GeneratePasswordFromPolicy_successful(t *testing.T) {
|
||||
policyName := "testpolicy"
|
||||
rawPolicy := map[string]interface{}{
|
||||
"policy": `length = 20
|
||||
rule "charset" {
|
||||
charset = "abcdefghijklmnopqrstuvwxyz"
|
||||
min_chars = 1
|
||||
var err error
|
||||
coreConfig := &CoreConfig{
|
||||
DisableMlock: true,
|
||||
DisableCache: true,
|
||||
Logger: log.NewNullLogger(),
|
||||
CredentialBackends: map[string]logical.Factory{},
|
||||
}
|
||||
rule "charset" {
|
||||
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
min_chars = 1
|
||||
}
|
||||
rule "charset" {
|
||||
charset = "0123456789"
|
||||
min_chars = 1
|
||||
}`,
|
||||
}
|
||||
marshalledPolicy, err := json.Marshal(rawPolicy)
|
||||
|
||||
cluster := NewTestCluster(t, coreConfig, &TestClusterOptions{})
|
||||
|
||||
cluster.Start()
|
||||
defer cluster.Cleanup()
|
||||
|
||||
core := cluster.Cores[0].Core
|
||||
TestWaitActive(t, core)
|
||||
|
||||
b64Policy := base64.StdEncoding.EncodeToString([]byte(rawTestPasswordPolicy))
|
||||
|
||||
path := fmt.Sprintf("sys/policies/password/%s", testPolicyName)
|
||||
req := logical.TestRequest(t, logical.CreateOperation, path)
|
||||
req.ClientToken = cluster.RootToken
|
||||
req.Data["policy"] = b64Policy
|
||||
|
||||
_, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up test: unable to marshal raw policy to JSON: %s", err)
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
testStorage := fakeBarrier{
|
||||
getEntry: &logical.StorageEntry{
|
||||
Key: getPasswordPolicyKey(policyName),
|
||||
Value: marshalledPolicy,
|
||||
},
|
||||
}
|
||||
|
||||
dsv := dynamicSystemView{
|
||||
core: &Core{
|
||||
systemBarrierView: NewBarrierView(testStorage, "sys/"),
|
||||
},
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ctx = namespace.RootContext(ctx)
|
||||
dsv := dynamicSystemView{core: cluster.Cores[0].Core}
|
||||
|
||||
runeset := map[rune]bool{}
|
||||
runesFound := []rune{}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
actual, err := dsv.GeneratePasswordFromPolicy(ctx, policyName)
|
||||
actual, err := dsv.GeneratePasswordFromPolicy(ctx, testPolicyName)
|
||||
if err != nil {
|
||||
t.Fatalf("no error expected, but got: %s", err)
|
||||
}
|
||||
|
@ -220,12 +234,6 @@ rule "charset" {
|
|||
}
|
||||
}
|
||||
|
||||
type runes []rune
|
||||
|
||||
func (r runes) Len() int { return len(r) }
|
||||
func (r runes) Less(i, j int) bool { return r[i] < r[j] }
|
||||
func (r runes) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||
|
||||
func TestDynamicSystemView_GeneratePasswordFromPolicy_failed(t *testing.T) {
|
||||
type testCase struct {
|
||||
policyName string
|
||||
|
@ -282,6 +290,12 @@ func TestDynamicSystemView_GeneratePasswordFromPolicy_failed(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type runes []rune
|
||||
|
||||
func (r runes) Len() int { return len(r) }
|
||||
func (r runes) Less(i, j int) bool { return r[i] < r[j] }
|
||||
func (r runes) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||
|
||||
type fakeBarrier struct {
|
||||
getEntry *logical.StorageEntry
|
||||
getErr error
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// +build !enterprise
|
||||
|
||||
package vault
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
passwordPolicySubPath = "password_policy/"
|
||||
)
|
||||
|
||||
// retrievePasswordPolicy retrieves a password policy from the logical storage
|
||||
func (d dynamicSystemView) retrievePasswordPolicy(ctx context.Context, policyName string) (*passwordPolicyConfig, error) {
|
||||
storage := d.core.systemBarrierView.SubView(passwordPolicySubPath)
|
||||
entry, err := storage.Get(ctx, policyName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
policyCfg := &passwordPolicyConfig{}
|
||||
err = json.Unmarshal(entry.Value, &policyCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal stored data: %w", err)
|
||||
}
|
||||
|
||||
return policyCfg, nil
|
||||
}
|
Loading…
Reference in New Issue