Update gcp secrets plugin

This commit is contained in:
Jeff Mitchell 2019-04-09 16:39:29 -04:00
parent 51b9895810
commit ab49700759
2 changed files with 115 additions and 57 deletions

View file

@ -69,33 +69,9 @@ func parseBindingObjList(topList *ast.ObjectList) (map[string]StringSet, error)
bindings := make(map[string]StringSet) bindings := make(map[string]StringSet)
for _, item := range topList.Items { for _, item := range topList.Items {
if len(item.Keys) != 2 { err := parseResourceObject(item, bindings)
merr = multierror.Append(merr, fmt.Errorf("invalid resource item does not have ID on line %d", item.Assign.Line)) if err != nil {
continue merr = multierror.Append(merr, fmt.Errorf("(line %d) %v", item.Assign.Line, err))
}
key := item.Keys[0].Token.Value().(string)
if key != "resource" {
merr = multierror.Append(merr, fmt.Errorf("invalid key '%s' (line %d)", key, item.Assign.Line))
continue
}
resourceName := item.Keys[1].Token.Value().(string)
_, ok := bindings[resourceName]
if !ok {
bindings[resourceName] = make(StringSet)
}
resourceList := item.Val.(*ast.ObjectType).List
for _, rolesItem := range resourceList.Items {
key := rolesItem.Keys[0].Token.Text
switch key {
case "roles":
parseRoles(rolesItem, bindings[resourceName], merr)
default:
merr = multierror.Append(merr, fmt.Errorf("invalid key '%s' in resource '%s' (line %d)", key, resourceName, item.Assign.Line))
continue
}
} }
} }
err := merr.ErrorOrNil() err := merr.ErrorOrNil()
@ -105,32 +81,114 @@ func parseBindingObjList(topList *ast.ObjectList) (map[string]StringSet, error)
return bindings, nil return bindings, nil
} }
func parseRoles(item *ast.ObjectItem, roleSet StringSet, merr *multierror.Error) { func parseResourceObject(item *ast.ObjectItem, bindings map[string]StringSet) error {
lst, ok := item.Val.(*ast.ListType) if len(item.Keys) != 2 || item.Keys[0] == nil || item.Keys[1] == nil {
return fmt.Errorf(`top-level items must have format "resource" "$resource_name"`)
}
k, err := parseStringFromObjectKey(item, item.Keys[0])
if err != nil {
return err
}
if k != "resource" {
return fmt.Errorf(`invalid item %q, expected "resource"`, k)
}
resourceName, err := parseStringFromObjectKey(item, item.Keys[1])
if err != nil {
return err
}
_, ok := bindings[resourceName]
if !ok { if !ok {
merr = multierror.Append(merr, fmt.Errorf("roles must be a list (line %d)", item.Assign.Line)) bindings[resourceName] = make(StringSet)
return }
boundRoles := bindings[resourceName]
resourceItemList := item.Val.(*ast.ObjectType).List
if resourceItemList == nil {
return fmt.Errorf("invalid empty roles list for item", item.Assign.Line)
} }
for _, roleItem := range lst.List { var merr *multierror.Error
role := roleItem.(*ast.LiteralType).Token.Value().(string) for _, rolesObj := range resourceItemList.Items {
err := parseRolesObject(rolesObj, boundRoles)
tkns := strings.Split(role, "/") if err != nil {
switch len(tkns) { merr = multierror.Append(merr, fmt.Errorf("role list (line %d): %v", rolesObj.Assign.Line, err))
case 2:
// "roles/X"
if tkns[0] == "roles" {
roleSet.Add(role)
continue
}
case 4:
// "projects/X/roles/Y" or "organizations/X/roles/Y"
if (tkns[0] == "projects" || tkns[0] == "organizations") && tkns[2] == "roles" {
roleSet.Add(role)
continue
}
} }
merr = multierror.Append(merr, fmt.Errorf("invalid role: %s (line %d): must be project-level, organization-level, or global role", role, roleItem.Pos().Line))
} }
return merr.ErrorOrNil()
}
func parseRolesObject(rolesObj *ast.ObjectItem, parsedRoles StringSet) error {
if rolesObj == nil || len(rolesObj.Keys) != 1 || rolesObj.Keys[0] == nil {
return fmt.Errorf(`expected "roles" list, got nil object item`)
}
k, err := parseStringFromObjectKey(rolesObj, rolesObj.Keys[0])
if err != nil {
return err
}
if k != "roles" {
return fmt.Errorf(`invalid key %q in resource, expected "roles"`, k)
}
if rolesObj.Val == nil {
return fmt.Errorf(`expected "roles" list, got nil value`)
}
roleList, ok := rolesObj.Val.(*ast.ListType)
if !ok {
return fmt.Errorf("parsing error, expected list of roles for key %q")
}
var merr *multierror.Error
for _, singleRoleObj := range roleList.List {
role, err := parseRole(rolesObj, singleRoleObj)
if err != nil {
merr = multierror.Append(merr, err)
} else {
parsedRoles.Add(role)
}
}
return merr.ErrorOrNil()
}
func parseRole(parent *ast.ObjectItem, roleNode ast.Node) (string, error) {
if roleNode == nil {
return "", fmt.Errorf(`unexpected empty role item (line %d)`, parent.Assign.Line)
}
roleLitType, ok := roleNode.(*ast.LiteralType)
if !ok || roleLitType == nil {
return "", fmt.Errorf(`unexpected nil item in roles list (line %d)`, parent.Assign.Line)
}
roleRaw := roleLitType.Token.Value()
role, ok := roleRaw.(string)
if !ok {
return "", fmt.Errorf(`unexpected item %v in roles list is not a string (line %d)`, roleRaw, parent.Assign.Line)
}
tkns := strings.Split(role, "/")
if len(tkns) == 2 && tkns[0] == "roles" {
return role, nil
}
if len(tkns) == 4 && tkns[2] == "roles" {
// "projects/X/roles/Y" or "organizations/X/roles/Y"
if tkns[0] == "projects" || tkns[0] == "organizations" {
return role, nil
}
}
return "", fmt.Errorf(`invalid role %q (line %d) must be one of following formats: "projects/X/roles/Y", "organizations/X/roles/Y", "roles/X"`, role, parent.Assign.Line)
}
func parseStringFromObjectKey(parent *ast.ObjectItem, k *ast.ObjectKey) (string, error) {
if k == nil || k.Token.Value() == nil {
return "", fmt.Errorf("expected string, got nil value (Llne %d)", parent.Assign.Line)
}
vRaw := k.Token.Value()
v, ok := vRaw.(string)
if !ok {
return "", fmt.Errorf("expected string, got %v (Llne %d)", parent.Assign.Line, vRaw)
}
return v, nil
} }

14
vendor/vendor.json vendored
View file

@ -1441,20 +1441,20 @@
{ {
"checksumSHA1": "QRHQkEIrTKzFEO3CNwo0jYNizxE=", "checksumSHA1": "QRHQkEIrTKzFEO3CNwo0jYNizxE=",
"path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin", "path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin",
"revision": "71903323ecb49843dd1118c3bf130fad306964e7", "revision": "d50d93bda84f7261388370df5fd1f663717c6d89",
"revisionTime": "2019-03-20T21:14:52Z" "revisionTime": "2019-04-09T20:36:38Z"
}, },
{ {
"checksumSHA1": "itK0aDL54CoWfKfpkCAp/7MdTgk=", "checksumSHA1": "itK0aDL54CoWfKfpkCAp/7MdTgk=",
"path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil", "path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil",
"revision": "71903323ecb49843dd1118c3bf130fad306964e7", "revision": "d50d93bda84f7261388370df5fd1f663717c6d89",
"revisionTime": "2019-03-20T21:14:52Z" "revisionTime": "2019-04-09T20:36:38Z"
}, },
{ {
"checksumSHA1": "81kYL49zTBoj1NYczxB2Xbr2d6Y=", "checksumSHA1": "gzBgQ4JmnODnpHQY2aqB6OCi36k=",
"path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin/util", "path": "github.com/hashicorp/vault-plugin-secrets-gcp/plugin/util",
"revision": "71903323ecb49843dd1118c3bf130fad306964e7", "revision": "d50d93bda84f7261388370df5fd1f663717c6d89",
"revisionTime": "2019-03-20T21:14:52Z" "revisionTime": "2019-04-09T20:36:38Z"
}, },
{ {
"checksumSHA1": "Kmkt2VgWs0WFq+8E1lnXhQow3w0=", "checksumSHA1": "Kmkt2VgWs0WFq+8E1lnXhQow3w0=",