mirror of
https://github.com/hashicorp/vault.git
synced 2026-06-09 00:33:28 -04:00
Merge remote-tracking branch 'remotes/from/ce/main'
Some checks are pending
build / setup (push) Waiting to run
build / Check ce/* Pull Requests (push) Blocked by required conditions
build / ui (push) Blocked by required conditions
build / artifacts-ce (push) Blocked by required conditions
build / artifacts-ent (push) Blocked by required conditions
build / hcp-setup (push) Waiting to run
build / hcp-image (push) Blocked by required conditions
build / test (push) Blocked by required conditions
build / test-hcp-image (push) Blocked by required conditions
build / completed-successfully (push) Blocked by required conditions
CI / setup (push) Waiting to run
CI / Run Autopilot upgrade tool (push) Blocked by required conditions
CI / Run Go tests (push) Blocked by required conditions
CI / Run Go tests tagged with testonly (push) Blocked by required conditions
CI / Run Go tests with data race detection (push) Blocked by required conditions
CI / Run Go tests with FIPS configuration (push) Blocked by required conditions
CI / Test UI (push) Blocked by required conditions
CI / tests-completed (push) Blocked by required conditions
Run linters / Setup (push) Waiting to run
Run linters / Deprecated functions (push) Blocked by required conditions
Run linters / Code checks (push) Blocked by required conditions
Run linters / Protobuf generate delta (push) Blocked by required conditions
Run linters / Format (push) Blocked by required conditions
Run linters / Semgrep (push) Waiting to run
Check Copywrite Headers / copywrite (push) Waiting to run
Security Scan / scan (push) Waiting to run
Some checks are pending
build / setup (push) Waiting to run
build / Check ce/* Pull Requests (push) Blocked by required conditions
build / ui (push) Blocked by required conditions
build / artifacts-ce (push) Blocked by required conditions
build / artifacts-ent (push) Blocked by required conditions
build / hcp-setup (push) Waiting to run
build / hcp-image (push) Blocked by required conditions
build / test (push) Blocked by required conditions
build / test-hcp-image (push) Blocked by required conditions
build / completed-successfully (push) Blocked by required conditions
CI / setup (push) Waiting to run
CI / Run Autopilot upgrade tool (push) Blocked by required conditions
CI / Run Go tests (push) Blocked by required conditions
CI / Run Go tests tagged with testonly (push) Blocked by required conditions
CI / Run Go tests with data race detection (push) Blocked by required conditions
CI / Run Go tests with FIPS configuration (push) Blocked by required conditions
CI / Test UI (push) Blocked by required conditions
CI / tests-completed (push) Blocked by required conditions
Run linters / Setup (push) Waiting to run
Run linters / Deprecated functions (push) Blocked by required conditions
Run linters / Code checks (push) Blocked by required conditions
Run linters / Protobuf generate delta (push) Blocked by required conditions
Run linters / Format (push) Blocked by required conditions
Run linters / Semgrep (push) Waiting to run
Check Copywrite Headers / copywrite (push) Waiting to run
Security Scan / scan (push) Waiting to run
This commit is contained in:
commit
a66dd1f3eb
2 changed files with 110 additions and 58 deletions
|
|
@ -27,6 +27,9 @@ var (
|
|||
const (
|
||||
ACLTemplating = iota // must be the first value for backwards compatibility
|
||||
JSONTemplating
|
||||
|
||||
// QuotedTemplating is like ACLTemplating, but quotes are escaped (for example `a "` becomes `a \"`)
|
||||
QuotedTemplating
|
||||
)
|
||||
|
||||
type PopulateStringInput struct {
|
||||
|
|
@ -53,19 +56,25 @@ type templateHandlerFunc func(interface{}, ...string) (string, error)
|
|||
// aclTemplateHandler processes known parameter data types when operating
|
||||
// in ACL mode.
|
||||
func aclTemplateHandler(v interface{}, keys ...string) (string, error) {
|
||||
return simpleTemplateHandler(v, keys, func(s string) string {
|
||||
return s
|
||||
})
|
||||
}
|
||||
|
||||
func simpleTemplateHandler(v interface{}, keys []string, quoteFunc func(s string) string) (string, error) {
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
if t == "" {
|
||||
return "", ErrTemplateValueNotFound
|
||||
}
|
||||
return t, nil
|
||||
return quoteFunc(t), nil
|
||||
case []string:
|
||||
return "", ErrTemplateValueNotFound
|
||||
case map[string]string:
|
||||
if len(keys) > 0 {
|
||||
val, ok := t[keys[0]]
|
||||
if ok {
|
||||
return val, nil
|
||||
return quoteFunc(val), nil
|
||||
}
|
||||
}
|
||||
return "", ErrTemplateValueNotFound
|
||||
|
|
@ -74,6 +83,17 @@ func aclTemplateHandler(v interface{}, keys ...string) (string, error) {
|
|||
return "", fmt.Errorf("unknown type: %T", v)
|
||||
}
|
||||
|
||||
// quotedTemplateHandler uses strconv.Quote to quote values
|
||||
func quotedTemplateHandler(v interface{}, keys ...string) (string, error) {
|
||||
return simpleTemplateHandler(v, keys, func(s string) string {
|
||||
escaped := strconv.Quote(s)
|
||||
if len(escaped) < 2 {
|
||||
return escaped
|
||||
}
|
||||
return escaped[1 : len(escaped)-1]
|
||||
})
|
||||
}
|
||||
|
||||
// jsonTemplateHandler processes known parameter data types when operating
|
||||
// in JSON mode.
|
||||
func jsonTemplateHandler(v interface{}, keys ...string) (string, error) {
|
||||
|
|
@ -120,6 +140,8 @@ func PopulateString(p PopulateStringInput) (bool, string, error) {
|
|||
p.templateHandler = aclTemplateHandler
|
||||
case JSONTemplating:
|
||||
p.templateHandler = jsonTemplateHandler
|
||||
case QuotedTemplating:
|
||||
p.templateHandler = quotedTemplateHandler
|
||||
default:
|
||||
return false, "", fmt.Errorf("unknown mode %q", p.Mode)
|
||||
}
|
||||
|
|
@ -235,7 +257,7 @@ func performTemplating(input string, p *PopulateStringInput) (string, error) {
|
|||
}
|
||||
}
|
||||
if alias == nil {
|
||||
if p.Mode == ACLTemplating {
|
||||
if p.Mode == ACLTemplating || p.Mode == QuotedTemplating {
|
||||
return "", errors.New("alias not found")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -380,7 +380,35 @@ func TestPopulate_Basic(t *testing.T) {
|
|||
aliasCustomMetadata: map[string]string{"foo": "abc", "bar": "123"},
|
||||
output: `{}`,
|
||||
},
|
||||
|
||||
// QuotedTemplating tests
|
||||
{
|
||||
mode: QuotedTemplating,
|
||||
name: "SPIFFE quote in the middle",
|
||||
input: "{{identity.entity.name}}",
|
||||
entityName: `entity"name`,
|
||||
output: `entity\"name`,
|
||||
},
|
||||
{
|
||||
mode: QuotedTemplating,
|
||||
name: "SPIFFE quoted value",
|
||||
input: "{{identity.entity.metadata.color}}",
|
||||
metadata: map[string]string{"color": `"green blue"`},
|
||||
output: `\"green blue\"`,
|
||||
},
|
||||
{
|
||||
mode: QuotedTemplating,
|
||||
name: "escaped alias accessor not found",
|
||||
input: "{{identity.entity.aliases.aws_123.custom_metadata.foo}}",
|
||||
aliasAccessor: "not_gonna_match",
|
||||
err: errors.New("alias not found"),
|
||||
},
|
||||
{
|
||||
mode: QuotedTemplating,
|
||||
name: "escaped metadata object disallowed",
|
||||
input: "{{identity.entity.metadata}}",
|
||||
metadata: map[string]string{"foo": "bar"},
|
||||
err: ErrTemplateValueNotFound,
|
||||
},
|
||||
// wildcard templating tests
|
||||
{
|
||||
name: "wildcard_glob_entity_injection",
|
||||
|
|
@ -485,67 +513,69 @@ path"secret/metadata/{{identity.entity.metadata.team}}/*" {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var entity *logical.Entity
|
||||
if !test.nilEntity {
|
||||
entity = &logical.Entity{
|
||||
ID: "entityID",
|
||||
Name: test.entityName,
|
||||
Metadata: test.metadata,
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var entity *logical.Entity
|
||||
if !test.nilEntity {
|
||||
entity = &logical.Entity{
|
||||
ID: "entityID",
|
||||
Name: test.entityName,
|
||||
Metadata: test.metadata,
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.aliasAccessor != "" {
|
||||
entity.Aliases = []*logical.Alias{
|
||||
{
|
||||
MountAccessor: test.aliasAccessor,
|
||||
ID: test.aliasID,
|
||||
Name: test.aliasName,
|
||||
Metadata: test.aliasMetadata,
|
||||
CustomMetadata: test.aliasCustomMetadata,
|
||||
},
|
||||
if test.aliasAccessor != "" {
|
||||
entity.Aliases = []*logical.Alias{
|
||||
{
|
||||
MountAccessor: test.aliasAccessor,
|
||||
ID: test.aliasID,
|
||||
Name: test.aliasName,
|
||||
Metadata: test.aliasMetadata,
|
||||
CustomMetadata: test.aliasCustomMetadata,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
var groups []*logical.Group
|
||||
if test.groupName != "" {
|
||||
groups = append(groups, &logical.Group{
|
||||
ID: "groupID",
|
||||
Name: test.groupName,
|
||||
Metadata: test.groupMetadata,
|
||||
NamespaceID: "root",
|
||||
})
|
||||
}
|
||||
|
||||
if test.groupMemberships != nil {
|
||||
for i, groupName := range test.groupMemberships {
|
||||
var groups []*logical.Group
|
||||
if test.groupName != "" {
|
||||
groups = append(groups, &logical.Group{
|
||||
ID: fmt.Sprintf("%s_%d", groupName, i),
|
||||
Name: groupName,
|
||||
ID: "groupID",
|
||||
Name: test.groupName,
|
||||
Metadata: test.groupMetadata,
|
||||
NamespaceID: "root",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
subst, out, err := PopulateString(PopulateStringInput{
|
||||
Mode: test.mode,
|
||||
ValidityCheckOnly: test.validityCheckOnly,
|
||||
String: test.input,
|
||||
Entity: entity,
|
||||
Groups: groups,
|
||||
NamespaceID: "root",
|
||||
Now: test.now,
|
||||
if test.groupMemberships != nil {
|
||||
for i, groupName := range test.groupMemberships {
|
||||
groups = append(groups, &logical.Group{
|
||||
ID: fmt.Sprintf("%s_%d", groupName, i),
|
||||
Name: groupName,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
subst, out, err := PopulateString(PopulateStringInput{
|
||||
Mode: test.mode,
|
||||
ValidityCheckOnly: test.validityCheckOnly,
|
||||
String: test.input,
|
||||
Entity: entity,
|
||||
Groups: groups,
|
||||
NamespaceID: "root",
|
||||
Now: test.now,
|
||||
})
|
||||
if err != nil {
|
||||
if test.err == nil {
|
||||
t.Fatalf("%s: expected success, got error: %v", test.name, err)
|
||||
}
|
||||
if err.Error() != test.err.Error() {
|
||||
t.Fatalf("%s: got error: %v", test.name, err)
|
||||
}
|
||||
}
|
||||
if out != test.output {
|
||||
t.Fatalf("%s: bad output: %s, expected: %s", test.name, out, test.output)
|
||||
}
|
||||
if err == nil && !subst && out != test.input {
|
||||
t.Fatalf("%s: bad subst flag", test.name)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
if test.err == nil {
|
||||
t.Fatalf("%s: expected success, got error: %v", test.name, err)
|
||||
}
|
||||
if err.Error() != test.err.Error() {
|
||||
t.Fatalf("%s: got error: %v", test.name, err)
|
||||
}
|
||||
}
|
||||
if out != test.output {
|
||||
t.Fatalf("%s: bad output: %s, expected: %s", test.name, out, test.output)
|
||||
}
|
||||
if err == nil && !subst && out != test.input {
|
||||
t.Fatalf("%s: bad subst flag", test.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue