-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move
random
helper from vault/helpers to shared lib (#122)
* copy over files from vault * include in ci
- Loading branch information
Showing
14 changed files
with
2,776 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ jobs: | |
"password", | ||
"plugincontainer", | ||
"pluginutil", | ||
"random", | ||
"reloadutil", | ||
"strutil", | ||
"temperror", | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module github.com/hashicorp/go-secure-stdlib/random | ||
|
||
go 1.22.1 | ||
|
||
require ( | ||
github.com/hashicorp/go-multierror v1.1.1 | ||
github.com/hashicorp/hcl v1.0.1-vault-5 | ||
github.com/mitchellh/mapstructure v1.5.0 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||
github.com/hashicorp/errwrap v1.1.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= | ||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= | ||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= | ||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= | ||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= | ||
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= | ||
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= | ||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= | ||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package random | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"unicode/utf8" | ||
|
||
"github.com/hashicorp/hcl" | ||
"github.com/mitchellh/mapstructure" | ||
) | ||
|
||
// ParsePolicy is a convenience function for parsing HCL into a StringGenerator. | ||
// See PolicyParser.ParsePolicy for details. | ||
func ParsePolicy(raw string) (gen StringGenerator, err error) { | ||
parser := PolicyParser{ | ||
RuleRegistry: Registry{ | ||
Rules: defaultRuleNameMapping, | ||
}, | ||
} | ||
return parser.ParsePolicy(raw) | ||
} | ||
|
||
// ParsePolicyBytes is a convenience function for parsing HCL into a StringGenerator. | ||
// See PolicyParser.ParsePolicy for details. | ||
func ParsePolicyBytes(raw []byte) (gen StringGenerator, err error) { | ||
return ParsePolicy(string(raw)) | ||
} | ||
|
||
// PolicyParser parses string generator configuration from HCL. | ||
type PolicyParser struct { | ||
// RuleRegistry maps rule names in HCL to Rule constructors. | ||
RuleRegistry Registry | ||
} | ||
|
||
// ParsePolicy parses the provided HCL into a StringGenerator. | ||
func (p PolicyParser) ParsePolicy(raw string) (sg StringGenerator, err error) { | ||
rawData := map[string]interface{}{} | ||
err = hcl.Decode(&rawData, raw) | ||
if err != nil { | ||
return sg, fmt.Errorf("unable to decode: %w", err) | ||
} | ||
|
||
// Decode the top level items | ||
gen := StringGenerator{} | ||
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ | ||
Result: &gen, | ||
DecodeHook: stringToRunesFunc, | ||
}) | ||
if err != nil { | ||
return sg, fmt.Errorf("unable to decode configuration: %w", err) | ||
} | ||
|
||
err = decoder.Decode(rawData) | ||
if err != nil { | ||
return sg, fmt.Errorf("failed to decode configuration: %w", err) | ||
} | ||
|
||
// Decode & parse rules | ||
rawRules, err := getMapSlice(rawData, "rule") | ||
if err != nil { | ||
return sg, fmt.Errorf("unable to retrieve rules: %w", err) | ||
} | ||
|
||
rules, err := parseRules(p.RuleRegistry, rawRules) | ||
if err != nil { | ||
return sg, fmt.Errorf("unable to parse rules: %w", err) | ||
} | ||
|
||
gen = StringGenerator{ | ||
Length: gen.Length, | ||
Rules: rules, | ||
} | ||
|
||
err = gen.validateConfig() | ||
if err != nil { | ||
return sg, err | ||
} | ||
|
||
return gen, nil | ||
} | ||
|
||
func parseRules(registry Registry, rawRules []map[string]interface{}) (rules []Rule, err error) { | ||
for _, rawRule := range rawRules { | ||
info, err := getRuleInfo(rawRule) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to get rule info: %w", err) | ||
} | ||
|
||
rule, err := registry.parseRule(info.ruleType, info.data) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to parse rule %s: %w", info.ruleType, err) | ||
} | ||
rules = append(rules, rule) | ||
} | ||
|
||
return rules, nil | ||
} | ||
|
||
// getMapSlice from the provided map. This will retrieve and type-assert a []map[string]interface{} from the map | ||
// This will not error if the key does not exist | ||
// This will return an error if the value at the provided key is not of type []map[string]interface{} | ||
func getMapSlice(m map[string]interface{}, key string) (mapSlice []map[string]interface{}, err error) { | ||
rawSlice, exists := m[key] | ||
if !exists { | ||
return nil, nil | ||
} | ||
|
||
mapSlice = []map[string]interface{}{} | ||
err = mapstructure.Decode(rawSlice, &mapSlice) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return mapSlice, nil | ||
} | ||
|
||
type ruleInfo struct { | ||
ruleType string | ||
data map[string]interface{} | ||
} | ||
|
||
// getRuleInfo splits the provided HCL-decoded rule into its rule type along with the data associated with it | ||
func getRuleInfo(rule map[string]interface{}) (data ruleInfo, err error) { | ||
// There should only be one key, but it's a dynamic key yay! | ||
for key := range rule { | ||
slice, err := getMapSlice(rule, key) | ||
if err != nil { | ||
return data, fmt.Errorf("unable to get rule data: %w", err) | ||
} | ||
|
||
if len(slice) == 0 { | ||
return data, fmt.Errorf("rule info cannot be empty") | ||
} | ||
|
||
data = ruleInfo{ | ||
ruleType: key, | ||
data: slice[0], | ||
} | ||
return data, nil | ||
} | ||
return data, fmt.Errorf("rule is empty") | ||
} | ||
|
||
// stringToRunesFunc converts a string to a []rune for use in the mapstructure library | ||
func stringToRunesFunc(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) { | ||
if from != reflect.String || to != reflect.Slice { | ||
return data, nil | ||
} | ||
|
||
raw := data.(string) | ||
|
||
if !utf8.ValidString(raw) { | ||
return nil, fmt.Errorf("invalid UTF8 string") | ||
} | ||
return []rune(raw), nil | ||
} |
Oops, something went wrong.