Update ad plugin (#4652)

This commit is contained in:
Becca Petrin 2018-05-29 16:16:43 -07:00 committed by GitHub
parent d9150969af
commit 13a0eebb67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 29 deletions

View file

@ -1,15 +1,17 @@
package plugin
type passwordConf struct {
TTL int `json:"ttl"`
MaxTTL int `json:"max_ttl"`
Length int `json:"length"`
TTL int `json:"ttl"`
MaxTTL int `json:"max_ttl"`
Length int `json:"length"`
Formatter string `json:"formatter"`
}
func (c *passwordConf) Map() map[string]interface{} {
return map[string]interface{}{
"ttl": c.TTL,
"max_ttl": c.MaxTTL,
"length": c.Length,
"ttl": c.TTL,
"max_ttl": c.MaxTTL,
"length": c.Length,
"formatter": c.Formatter,
}
}

View file

@ -3,7 +3,6 @@ package plugin
import (
"context"
"errors"
"fmt"
"github.com/hashicorp/vault-plugin-secrets-ad/plugin/util"
"github.com/hashicorp/vault/helper/ldaputil"
@ -67,6 +66,10 @@ func (b *backend) configFields() map[string]*framework.FieldSchema {
Default: defaultPasswordLength,
Description: "The desired length of passwords that Vault generates.",
}
fields["formatter"] = &framework.FieldSchema{
Type: framework.TypeString,
Description: `Text to insert the password into, ex. "customPrefix{{PASSWORD}}customSuffix".`,
}
return fields
}
@ -84,6 +87,7 @@ func (b *backend) configUpdateOperation(ctx context.Context, req *logical.Reques
ttl := fieldData.Get("ttl").(int)
maxTTL := fieldData.Get("max_ttl").(int)
length := fieldData.Get("length").(int)
formatter := fieldData.Get("formatter").(string)
if ttl == 0 {
ttl = int(b.System().DefaultLeaseTTL().Seconds())
@ -100,13 +104,15 @@ func (b *backend) configUpdateOperation(ctx context.Context, req *logical.Reques
if maxTTL < 1 {
return nil, errors.New("max_ttl must be positive")
}
if length < util.MinimumPasswordLength {
return nil, fmt.Errorf("minimum password length is %d for sufficient complexity to be secure, though Vault recommends a higher length", util.MinimumPasswordLength)
if err := util.ValidatePwdSettings(formatter, length); err != nil {
return nil, err
}
passwordConf := &passwordConf{
TTL: ttl,
MaxTTL: maxTTL,
Length: length,
TTL: ttl,
MaxTTL: maxTTL,
Length: length,
Formatter: formatter,
}
config := &configuration{passwordConf, activeDirectoryConf}

View file

@ -158,7 +158,7 @@ func (b *backend) generateAndReturnCreds(ctx context.Context, storage logical.St
return nil, errors.New("the config is currently unset")
}
newPassword, err := util.GeneratePassword(engineConf.PasswordConf.Length)
newPassword, err := util.GeneratePassword(engineConf.PasswordConf.Formatter, engineConf.PasswordConf.Length)
if err != nil {
return nil, err
}

View file

@ -3,6 +3,7 @@ package util
import (
"encoding/base64"
"fmt"
"strings"
"github.com/hashicorp/go-uuid"
)
@ -12,19 +13,59 @@ var (
minimumLengthOfComplexString = 8
PasswordComplexityPrefix = "?@09AZ"
MinimumPasswordLength = len(PasswordComplexityPrefix) + minimumLengthOfComplexString
PwdFieldTmpl = "{{PASSWORD}}"
)
func GeneratePassword(desiredLength int) (string, error) {
if desiredLength < MinimumPasswordLength {
return "", fmt.Errorf("it's not possible to generate a _secure_ password of length %d, please boost length to %d, though Vault recommends higher", desiredLength, MinimumPasswordLength)
func GeneratePassword(formatter string, totalLength int) (string, error) {
if err := ValidatePwdSettings(formatter, totalLength); err != nil {
return "", err
}
pwd, err := generatePassword(totalLength)
if err != nil {
return "", err
}
if formatter == "" {
pwd = PasswordComplexityPrefix + pwd
return pwd[:totalLength], nil
}
return strings.Replace(formatter, PwdFieldTmpl, pwd[:lengthOfPassword(formatter, totalLength)], 1), nil
}
func ValidatePwdSettings(formatter string, totalLength int) error {
// Check for if there's no formatter.
if formatter == "" {
if totalLength < len(PasswordComplexityPrefix)+minimumLengthOfComplexString {
return fmt.Errorf("it's not possible to generate a _secure_ password of length %d, please boost length to %d, though Vault recommends higher", totalLength, minimumLengthOfComplexString)
}
return nil
}
// Check for if there is a formatter.
if lengthOfPassword(formatter, totalLength) < minimumLengthOfComplexString {
return fmt.Errorf("since the desired length is %d, it isn't possible to generate a sufficiently complex password - please increase desired length or remove characters from the formatter", totalLength)
}
numPwdFields := strings.Count(formatter, PwdFieldTmpl)
if numPwdFields == 0 {
return fmt.Errorf("%s must contain password replacement field of %s", formatter, PwdFieldTmpl)
}
if numPwdFields > 1 {
return fmt.Errorf("%s must contain ONE password replacement field of %s", formatter, PwdFieldTmpl)
}
return nil
}
func lengthOfPassword(formatter string, totalLength int) int {
lengthOfText := len(formatter) - len(PwdFieldTmpl)
return totalLength - lengthOfText
}
// generatePassword returns a password of a length AT LEAST as long as the desired length,
// it may be longer.
func generatePassword(desiredLength int) (string, error) {
b, err := uuid.GenerateRandomBytes(desiredLength)
if err != nil {
return "", err
}
result := ""
// Though the result should immediately be longer than the desiredLength,
// do this in a loop to ensure there's absolutely no risk of a panic when slicing it down later.
@ -32,7 +73,5 @@ func GeneratePassword(desiredLength int) (string, error) {
// Encode to base64 because it's more complex.
result += base64.StdEncoding.EncodeToString(b)
}
result = PasswordComplexityPrefix + result
return result[:desiredLength], nil
return result, nil
}

16
vendor/vendor.json vendored
View file

@ -1321,22 +1321,22 @@
"revisionTime": "2018-04-03T19:54:48Z"
},
{
"checksumSHA1": "B8KN0npDVBBnSDoL8htTSBpFgZ0=",
"checksumSHA1": "vCJEdTDszlvEQUqrT/RC7Q31J3g=",
"path": "github.com/hashicorp/vault-plugin-secrets-ad/plugin",
"revision": "321ea9aa40719a982e9ad39fecd911a212d0d7c0",
"revisionTime": "2018-05-24T23:02:05Z"
"revision": "18300aa1c7e4c3433afe92c74b53278f617d19bf",
"revisionTime": "2018-05-29T21:38:19Z"
},
{
"checksumSHA1": "qHGmA9y3hKMBSLRWLifD37EaHP4=",
"path": "github.com/hashicorp/vault-plugin-secrets-ad/plugin/client",
"revision": "321ea9aa40719a982e9ad39fecd911a212d0d7c0",
"revisionTime": "2018-05-24T23:02:05Z"
"revision": "18300aa1c7e4c3433afe92c74b53278f617d19bf",
"revisionTime": "2018-05-29T21:38:19Z"
},
{
"checksumSHA1": "/wFdQSWF1zexkefiI7j+LrREMHk=",
"checksumSHA1": "f5N0jlhC8c2vq0zez81fezfas/o=",
"path": "github.com/hashicorp/vault-plugin-secrets-ad/plugin/util",
"revision": "321ea9aa40719a982e9ad39fecd911a212d0d7c0",
"revisionTime": "2018-05-24T23:02:05Z"
"revision": "18300aa1c7e4c3433afe92c74b53278f617d19bf",
"revisionTime": "2018-05-29T21:38:19Z"
},
{
"checksumSHA1": "0BXf2h4FJSUTdVK3m75a1KXnYVA=",