Update gcp secrets plugin (#9004)
This commit is contained in:
parent
eb0b3ac286
commit
34fab8ae09
2
go.mod
2
go.mod
|
@ -86,7 +86,7 @@ require (
|
|||
github.com/hashicorp/vault-plugin-secrets-ad v0.6.4-beta1.0.20200518124111-3dceeb3ce90e
|
||||
github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.5
|
||||
github.com/hashicorp/vault-plugin-secrets-azure v0.5.6
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.1
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.2
|
||||
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.5
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.5.5
|
||||
github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.1.2
|
||||
|
|
2
go.sum
2
go.sum
|
@ -508,6 +508,8 @@ github.com/hashicorp/vault-plugin-secrets-azure v0.5.6 h1:4PgQ5rCT29wW5PMyebEhPk
|
|||
github.com/hashicorp/vault-plugin-secrets-azure v0.5.6/go.mod h1:Q0cIL4kZWnMmQWkBfWtyOd7+JXTEpAyU4L932PMHq3E=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.1 h1:APkzBSHo+sKeWxXCM1aGGwcbfKfVQFN3CHmNGHyfqL0=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.1/go.mod h1:jVTE1fuhRcBOb/gnCT9W++AnlwiyQEX4S8iVCKhKQsE=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.2 h1:ovziWUzmj83UlVXK8tM926ZitLKa5ZwRvlMqVibWHEs=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp v0.6.2/go.mod h1:psRQ/dm5XatoUKLDUeWrpP9icMJNtu/jmscUr37YGK4=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.5 h1:NigzA2v+h+cjBPl41pRirRwWELF+RPJGch/ys0Sijrc=
|
||||
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.5/go.mod h1:b6RwFD1bny1zbfqhD35iGJdQYHRtJLx3HfBD109GO38=
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.5.5 h1:yLtfsAiJOkpRkk+OxQmFluQJ35OUw420Y+CwfGMWuSc=
|
||||
|
|
|
@ -33,7 +33,7 @@ type backend struct {
|
|||
// cache directly.
|
||||
cache *cache.Cache
|
||||
|
||||
iamResources iamutil.IamResourceParser
|
||||
resources iamutil.ResourceParser
|
||||
|
||||
rolesetLock sync.Mutex
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
|
|||
func Backend() *backend {
|
||||
var b = &backend{
|
||||
cache: cache.New(),
|
||||
iamResources: iamutil.GetEnabledIamResources(),
|
||||
resources: iamutil.GetEnabledResources(),
|
||||
}
|
||||
|
||||
b.Backend = &framework.Backend{
|
||||
|
|
120
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/api_handle.go
generated
vendored
Normal file
120
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/api_handle.go
generated
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
package iamutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
type ApiHandle struct {
|
||||
c *http.Client
|
||||
userAgent string
|
||||
}
|
||||
|
||||
func GetApiHandle(client *http.Client, userAgent string) *ApiHandle {
|
||||
return &ApiHandle{
|
||||
c: client,
|
||||
userAgent: userAgent,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ApiHandle) DoGetRequest(ctx context.Context, r Resource, out interface{}) (err error) {
|
||||
config := r.GetConfig()
|
||||
req, err := constructRequest(r, &config.GetMethod, nil)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Unable to construct Get request: {{err}}", err)
|
||||
}
|
||||
return h.doRequest(ctx, req, out)
|
||||
}
|
||||
|
||||
func (h *ApiHandle) DoSetRequest(ctx context.Context, r Resource, data io.Reader, out interface{}) error {
|
||||
config := r.GetConfig()
|
||||
req, err := constructRequest(r, &config.SetMethod, data)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Unable to construct Set request: {{err}}", err)
|
||||
}
|
||||
return h.doRequest(ctx, req, out)
|
||||
}
|
||||
|
||||
func (h *ApiHandle) doRequest(ctx context.Context, req *http.Request, out interface{}) error {
|
||||
if req.Header == nil {
|
||||
req.Header = make(http.Header)
|
||||
}
|
||||
if h.userAgent != "" {
|
||||
req.Header.Set("User-Agent", h.userAgent)
|
||||
}
|
||||
|
||||
resp, err := h.c.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer googleapi.CloseBody(resp)
|
||||
|
||||
if err := googleapi.CheckResponse(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
|
||||
return errwrap.Wrapf("unable to decode JSON resp to output interface: {{err}}", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func constructRequest(r Resource, restMethod *RestMethod, data io.Reader) (*http.Request, error) {
|
||||
config := r.GetConfig()
|
||||
if data == nil && config != nil && config.Service == "cloudresourcemanager" {
|
||||
// In order to support Resource Manager policies with conditional bindings,
|
||||
// we need to request the policy version of 3. This request parameter is backwards compatible
|
||||
// and will return version 1 policies if they are not yet updated to version 3.
|
||||
requestPolicyVersion3 := `{"options": {"requestedPolicyVersion": 3}}`
|
||||
data = strings.NewReader(requestPolicyVersion3)
|
||||
}
|
||||
req, err := http.NewRequest(
|
||||
restMethod.HttpMethod,
|
||||
googleapi.ResolveRelative(restMethod.BaseURL, restMethod.Path),
|
||||
data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Header == nil {
|
||||
req.Header = make(http.Header)
|
||||
}
|
||||
if data != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
relId := r.GetRelativeId()
|
||||
replacementMap := make(map[string]string)
|
||||
|
||||
if strings.Contains(restMethod.Path, "{+resource}") {
|
||||
// +resource is used to represent full relative resource name
|
||||
if len(config.Parameters) == 1 && config.Parameters[0] == "resource" {
|
||||
relName := ""
|
||||
tkns := strings.Split(config.TypeKey, "/")
|
||||
for _, colId := range tkns {
|
||||
if colName, ok := relId.IdTuples[colId]; ok {
|
||||
relName += fmt.Sprintf("%s/%s/", colId, colName)
|
||||
}
|
||||
}
|
||||
replacementMap["resource"] = strings.Trim(relName, "/")
|
||||
}
|
||||
} else {
|
||||
for colId, resId := range relId.IdTuples {
|
||||
rId, ok := config.CollectionReplacementKeys[colId]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected value for collection id %s", colId)
|
||||
}
|
||||
replacementMap[rId] = resId
|
||||
}
|
||||
}
|
||||
|
||||
googleapi.Expand(req.URL, replacementMap)
|
||||
return req, nil
|
||||
}
|
142
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/dataset_resource.go
generated
vendored
Normal file
142
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/dataset_resource.go
generated
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
package iamutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-gcp-common/gcputil"
|
||||
)
|
||||
|
||||
// NOTE: BigQuery does not conform to the typical REST for IAM policies
|
||||
// instead it has an access array with bindings on the dataset
|
||||
// object. https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#Dataset
|
||||
type AccessBinding struct {
|
||||
Role string `json:"role,omitempty"`
|
||||
UserByEmail string `json:"userByEmail,omitempty"`
|
||||
GroupByEmail string `json:"groupByEmail,omitempty"`
|
||||
}
|
||||
|
||||
type Dataset struct {
|
||||
Access []*AccessBinding `json:"access,omitempty"`
|
||||
Etag string `json:"etag,omitempty"`
|
||||
}
|
||||
|
||||
// NOTE: DatasetResource implements IamResource.
|
||||
// This is because bigquery datasets have their own
|
||||
// ACLs instead of an IAM policy
|
||||
type DatasetResource struct {
|
||||
relativeId *gcputil.RelativeResourceName
|
||||
config *RestResource
|
||||
}
|
||||
|
||||
func (r *DatasetResource) GetConfig() *RestResource {
|
||||
return r.config
|
||||
}
|
||||
|
||||
func (r *DatasetResource) GetRelativeId() *gcputil.RelativeResourceName {
|
||||
return r.relativeId
|
||||
}
|
||||
|
||||
func (r *DatasetResource) GetIamPolicy(ctx context.Context, h *ApiHandle) (*Policy, error) {
|
||||
var dataset Dataset
|
||||
if err := h.DoGetRequest(ctx, r, &dataset); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to get BigQuery Dataset ACL: {{err}}", err)
|
||||
}
|
||||
p := datasetAsPolicy(&dataset)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (r *DatasetResource) SetIamPolicy(ctx context.Context, h *ApiHandle, p *Policy) (*Policy, error) {
|
||||
var jsonP []byte
|
||||
ds, err := policyAsDataset(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonP, err = json.Marshal(ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqJson := fmt.Sprintf(r.config.SetMethod.RequestFormat, jsonP)
|
||||
if !json.Valid([]byte(reqJson)) {
|
||||
return nil, fmt.Errorf("request format from generated BigQuery Dataset config invalid JSON: %s", reqJson)
|
||||
}
|
||||
|
||||
var dataset Dataset
|
||||
if err := h.DoSetRequest(ctx, r, strings.NewReader(reqJson), &dataset); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to set BigQuery Dataset ACL: {{err}}", err)
|
||||
}
|
||||
policy := datasetAsPolicy(&dataset)
|
||||
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func policyAsDataset(p *Policy) (*Dataset, error) {
|
||||
if p == nil {
|
||||
return nil, errors.New("Policy cannot be nil")
|
||||
}
|
||||
|
||||
ds := &Dataset{Etag: p.Etag}
|
||||
for _, binding := range p.Bindings {
|
||||
if binding.Condition != nil {
|
||||
return nil, errors.New("Bigquery Datasets do not support conditional IAM")
|
||||
}
|
||||
for _, member := range binding.Members {
|
||||
var email, iamType string
|
||||
memberSplit := strings.Split(member, ":")
|
||||
if len(memberSplit) == 2 {
|
||||
iamType = memberSplit[0]
|
||||
email = memberSplit[1]
|
||||
} else {
|
||||
email = member
|
||||
}
|
||||
|
||||
if email != "" {
|
||||
binding := &AccessBinding{Role: binding.Role}
|
||||
if iamType == "group" {
|
||||
binding.GroupByEmail = email
|
||||
} else {
|
||||
binding.UserByEmail = email
|
||||
}
|
||||
ds.Access = append(ds.Access, binding)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
func datasetAsPolicy(ds *Dataset) *Policy {
|
||||
if ds == nil {
|
||||
return &Policy{}
|
||||
}
|
||||
|
||||
policy := &Policy{Etag: ds.Etag}
|
||||
bindingMap := make(map[string]*Binding)
|
||||
for _, accessBinding := range ds.Access {
|
||||
var iamMember string
|
||||
|
||||
//NOTE: Can either have GroupByEmail or UserByEmail but not both
|
||||
if accessBinding.GroupByEmail != "" {
|
||||
iamMember = fmt.Sprintf("group:%s", accessBinding.GroupByEmail)
|
||||
} else if strings.HasSuffix(accessBinding.UserByEmail, "gserviceaccount.com") {
|
||||
iamMember = fmt.Sprintf("serviceAccount:%s", accessBinding.UserByEmail)
|
||||
} else {
|
||||
iamMember = fmt.Sprintf("user:%s", accessBinding.UserByEmail)
|
||||
}
|
||||
if binding, ok := bindingMap[accessBinding.Role]; ok {
|
||||
binding.Members = append(binding.Members, iamMember)
|
||||
} else {
|
||||
bindingMap[accessBinding.Role] = &Binding{
|
||||
Role: accessBinding.Role,
|
||||
Members: []string{iamMember},
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range bindingMap {
|
||||
policy.Bindings = append(policy.Bindings, v)
|
||||
}
|
||||
return policy
|
||||
}
|
70
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/iam_handle.go
generated
vendored
70
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/iam_handle.go
generated
vendored
|
@ -1,70 +0,0 @@
|
|||
package iamutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
type IamHandle struct {
|
||||
c *http.Client
|
||||
userAgent string
|
||||
}
|
||||
|
||||
func GetIamHandle(client *http.Client, userAgent string) *IamHandle {
|
||||
return &IamHandle{
|
||||
c: client,
|
||||
userAgent: userAgent,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *IamHandle) GetIamPolicy(ctx context.Context, r IamResource) (*Policy, error) {
|
||||
req, err := r.GetIamPolicyRequest()
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("unable to construct GetIamPolicy request: {{err}}", err)
|
||||
}
|
||||
var p Policy
|
||||
if err := h.doRequest(ctx, req, &p); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to get policy: {{err}}", err)
|
||||
}
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (h *IamHandle) SetIamPolicy(ctx context.Context, r IamResource, p *Policy) (*Policy, error) {
|
||||
req, err := r.SetIamPolicyRequest(p)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("unable to construct SetIamPolicy request: {{err}}", err)
|
||||
}
|
||||
var out Policy
|
||||
if err := h.doRequest(ctx, req, &out); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to set policy: {{err}}", err)
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (h *IamHandle) doRequest(ctx context.Context, req *http.Request, out interface{}) error {
|
||||
if req.Header == nil {
|
||||
req.Header = make(http.Header)
|
||||
}
|
||||
if h.userAgent != "" {
|
||||
req.Header.Set("User-Agent", h.userAgent)
|
||||
}
|
||||
|
||||
resp, err := h.c.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer googleapi.CloseBody(resp)
|
||||
|
||||
if err := googleapi.CheckResponse(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
|
||||
return errwrap.Wrapf("unable to decode JSON resp to output interface: {{err}}", err)
|
||||
}
|
||||
return nil
|
||||
}
|
127
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/iam_resource.go
generated
vendored
127
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/iam_resource.go
generated
vendored
|
@ -1,130 +1,49 @@
|
|||
package iamutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-gcp-common/gcputil"
|
||||
"google.golang.org/api/googleapi"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IamResource handles constructing HTTP requests for getting and
|
||||
// setting IAM policies.
|
||||
type IamResource interface {
|
||||
GetIamPolicyRequest() (*http.Request, error)
|
||||
SetIamPolicyRequest(*Policy) (req *http.Request, err error)
|
||||
}
|
||||
|
||||
// parsedIamResource implements IamResource.
|
||||
type parsedIamResource struct {
|
||||
// IamResource implements Resource.
|
||||
type IamResource struct {
|
||||
relativeId *gcputil.RelativeResourceName
|
||||
config *IamRestResource
|
||||
config *RestResource
|
||||
}
|
||||
|
||||
type IamRestResource struct {
|
||||
// Name is the base name of the resource
|
||||
// i.e. for a GCE instance: "instance"
|
||||
Name string
|
||||
|
||||
// Type Key is the identifying path for the resource, or
|
||||
// the RESTful resource identifier without resource IDs
|
||||
// i.e. For a GCE instance: "projects/zones/instances"
|
||||
TypeKey string
|
||||
|
||||
// Service Information
|
||||
// Service is the name of the service this resource belongs to.
|
||||
Service string
|
||||
|
||||
// IsPreferredVersion is true if this version of the API/resource is preferred.
|
||||
IsPreferredVersion bool
|
||||
|
||||
// IsPreferredVersion is true if this version of the API/resource is preferred.
|
||||
GetMethod RestMethod
|
||||
|
||||
// IsPreferredVersion is true if this version of the API/resource is preferred.
|
||||
SetMethod RestMethod
|
||||
|
||||
// Ordered parameters to be replaced in method paths
|
||||
Parameters []string
|
||||
|
||||
// collection Id --> parameter to be replaced {} name
|
||||
CollectionReplacementKeys map[string]string
|
||||
func (r *IamResource) GetConfig() *RestResource {
|
||||
return r.config
|
||||
}
|
||||
|
||||
type RestMethod struct {
|
||||
HttpMethod string
|
||||
BaseURL string
|
||||
Path string
|
||||
RequestFormat string
|
||||
func (r *IamResource) GetRelativeId() *gcputil.RelativeResourceName {
|
||||
return r.relativeId
|
||||
}
|
||||
|
||||
func (r *parsedIamResource) SetIamPolicyRequest(p *Policy) (req *http.Request, err error) {
|
||||
func (r *IamResource) GetIamPolicy(ctx context.Context, h *ApiHandle) (*Policy, error) {
|
||||
var p Policy
|
||||
if err := h.DoGetRequest(ctx, r, &p); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to get policy: {{err}}", err)
|
||||
}
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (r *IamResource) SetIamPolicy(ctx context.Context, h *ApiHandle, p *Policy) (*Policy, error) {
|
||||
jsonP, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqJson := fmt.Sprintf(r.config.SetMethod.RequestFormat, jsonP)
|
||||
if !json.Valid([]byte(reqJson)) {
|
||||
return nil, fmt.Errorf("request format from generated IAM config invalid JSON: %s", reqJson)
|
||||
}
|
||||
|
||||
return r.constructRequest(&r.config.SetMethod, strings.NewReader(reqJson))
|
||||
}
|
||||
|
||||
var requestPolicyVersion3 = `{"options": {"requestedPolicyVersion": 3}}`
|
||||
|
||||
func (r *parsedIamResource) GetIamPolicyRequest() (*http.Request, error) {
|
||||
// In order to support Resource Manager policies with conditional bindings,
|
||||
// we need to request the policy version of 3. This request parameter is backwards compatible
|
||||
// and will return version 1 policies if they are not yet updated to version 3.
|
||||
if r.config != nil && r.config.Service == "cloudresourcemanager" {
|
||||
return r.constructRequest(&r.config.GetMethod, strings.NewReader(requestPolicyVersion3))
|
||||
}
|
||||
return r.constructRequest(&r.config.GetMethod, nil)
|
||||
}
|
||||
|
||||
func (r *parsedIamResource) constructRequest(restMethod *RestMethod, data io.Reader) (*http.Request, error) {
|
||||
req, err := http.NewRequest(
|
||||
restMethod.HttpMethod,
|
||||
googleapi.ResolveRelative(restMethod.BaseURL, restMethod.Path),
|
||||
data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Header == nil {
|
||||
req.Header = make(http.Header)
|
||||
}
|
||||
if data != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
relId := r.relativeId
|
||||
replacementMap := make(map[string]string)
|
||||
|
||||
if strings.Contains(restMethod.Path, "{+resource}") {
|
||||
// +resource is used to represent full relative resource name
|
||||
if len(r.config.Parameters) == 1 && r.config.Parameters[0] == "resource" {
|
||||
relName := ""
|
||||
tkns := strings.Split(r.config.TypeKey, "/")
|
||||
for _, colId := range tkns {
|
||||
relName += fmt.Sprintf("%s/%s/", colId, relId.IdTuples[colId])
|
||||
}
|
||||
replacementMap["resource"] = strings.Trim(relName, "/")
|
||||
}
|
||||
} else {
|
||||
for colId, resId := range relId.IdTuples {
|
||||
rId, ok := r.config.CollectionReplacementKeys[colId]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected value for collection id %s", colId)
|
||||
}
|
||||
replacementMap[rId] = resId
|
||||
}
|
||||
}
|
||||
|
||||
googleapi.Expand(req.URL, replacementMap)
|
||||
return req, nil
|
||||
var policy Policy
|
||||
if err := h.DoSetRequest(ctx, r, strings.NewReader(reqJson), &policy); err != nil {
|
||||
return nil, errwrap.Wrapf("unable to set policy: {{err}}", err)
|
||||
}
|
||||
return &policy, nil
|
||||
}
|
||||
|
|
52
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/resource.go
generated
vendored
Normal file
52
vendor/github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil/resource.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
package iamutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/go-gcp-common/gcputil"
|
||||
)
|
||||
|
||||
// Resource handles constructing HTTP requests for getting and
|
||||
// setting IAM policies.
|
||||
type Resource interface {
|
||||
GetIamPolicy(context.Context, *ApiHandle) (*Policy, error)
|
||||
SetIamPolicy(context.Context, *ApiHandle, *Policy) (*Policy, error)
|
||||
GetConfig() *RestResource
|
||||
GetRelativeId() *gcputil.RelativeResourceName
|
||||
}
|
||||
|
||||
type RestResource struct {
|
||||
// Name is the base name of the resource
|
||||
// i.e. for a GCE instance: "instance"
|
||||
Name string
|
||||
|
||||
// TypeKey is the identifying path for the resource, or
|
||||
// the RESTful resource identifier without resource IDs
|
||||
// i.e. For a GCE instance: "projects/zones/instances"
|
||||
TypeKey string
|
||||
|
||||
// Service is the name of the service this resource belongs to.
|
||||
Service string
|
||||
|
||||
// IsPreferredVersion is true if this version of the API/resource is preferred.
|
||||
IsPreferredVersion bool
|
||||
|
||||
// HTTP metadata for getting Policy data in GCP
|
||||
GetMethod RestMethod
|
||||
|
||||
// HTTP metadata for setting Policy data in GCP
|
||||
SetMethod RestMethod
|
||||
|
||||
// Ordered parameters to be replaced in method paths
|
||||
Parameters []string
|
||||
|
||||
// Mapping of collection ids onto the parameter to be replaced
|
||||
CollectionReplacementKeys map[string]string
|
||||
}
|
||||
|
||||
type RestMethod struct {
|
||||
HttpMethod string
|
||||
BaseURL string
|
||||
Path string
|
||||
RequestFormat string
|
||||
}
|
|
@ -14,17 +14,17 @@ const (
|
|||
errorMultipleVersions = `please provide a self-link with version instead; multiple versions of this resource exist, all non-preferred`
|
||||
)
|
||||
|
||||
// IamResourceParser handles parsing resource ID and REST
|
||||
// ResourceParser handles parsing resource ID and REST
|
||||
// config from a given resource ID or name.
|
||||
type IamResourceParser interface {
|
||||
Parse(string) (IamResource, error)
|
||||
type ResourceParser interface {
|
||||
Parse(string) (Resource, error)
|
||||
}
|
||||
|
||||
// GeneratedResources implements IamResourceParser - a value
|
||||
// GeneratedResources implements ResourceParser - a value
|
||||
// is generated using internal/generate_iam.go
|
||||
type GeneratedResources map[string]map[string]map[string]IamRestResource
|
||||
type GeneratedResources map[string]map[string]map[string]RestResource
|
||||
|
||||
func getResourceFromVersions(rawName string, versionMap map[string]IamRestResource) (*IamRestResource, error) {
|
||||
func getResourceFromVersions(rawName string, versionMap map[string]RestResource) (*RestResource, error) {
|
||||
possibleVer := make([]string, 0, len(versionMap))
|
||||
for v, config := range versionMap {
|
||||
if config.IsPreferredVersion || len(versionMap) == 1 {
|
||||
|
@ -45,10 +45,10 @@ func getResourceFromVersions(rawName string, versionMap map[string]IamRestResour
|
|||
return nil, fmt.Errorf(resourceParsingErrorTmpl, rawName, errorMultipleVersions)
|
||||
}
|
||||
|
||||
func (apis GeneratedResources) GetRestConfig(rawName string, fullName *gcputil.FullResourceName, prefix string) (*IamRestResource, error) {
|
||||
func (apis GeneratedResources) GetRestConfig(rawName string, fullName *gcputil.FullResourceName, prefix string) (*RestResource, error) {
|
||||
relName := fullName.RelativeResourceName
|
||||
if relName == nil {
|
||||
return nil, fmt.Errorf(resourceParsingErrorTmpl, rawName, fmt.Errorf("unsupported resource type: %s", rawName))
|
||||
return nil, fmt.Errorf(resourceParsingErrorTmpl, rawName, fmt.Errorf("relative name does not exist: %s", rawName))
|
||||
}
|
||||
|
||||
serviceMap, ok := apis[relName.TypeKey]
|
||||
|
@ -80,7 +80,7 @@ func (apis GeneratedResources) GetRestConfig(rawName string, fullName *gcputil.F
|
|||
return nil, fmt.Errorf(resourceParsingErrorTmpl, rawName, errorMultipleServices)
|
||||
}
|
||||
|
||||
func (apis GeneratedResources) Parse(rawName string) (IamResource, error) {
|
||||
func (apis GeneratedResources) Parse(rawName string) (Resource, error) {
|
||||
rUrl, err := url.Parse(rawName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`resource "%s" is invalid URI`, rawName)
|
||||
|
@ -123,8 +123,10 @@ func (apis GeneratedResources) Parse(rawName string) (IamResource, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &parsedIamResource{
|
||||
relativeId: relName,
|
||||
config: cfg,
|
||||
}, nil
|
||||
switch cfg.TypeKey {
|
||||
case "projects/dataset":
|
||||
return &DatasetResource{relativeId: relName, config: cfg}, nil
|
||||
default:
|
||||
return &IamResource{relativeId: relName, config: cfg}, nil
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -236,7 +236,7 @@ func (b *backend) pathRoleSetDelete(ctx context.Context, req *logical.Request, d
|
|||
return nil, err
|
||||
}
|
||||
|
||||
iamHandle := iamutil.GetIamHandle(httpC, useragent.String())
|
||||
apiHandle := iamutil.GetApiHandle(httpC, useragent.String())
|
||||
|
||||
warnings := make([]string, 0)
|
||||
if rs.AccountId != nil {
|
||||
|
@ -250,7 +250,7 @@ func (b *backend) pathRoleSetDelete(ctx context.Context, req *logical.Request, d
|
|||
warnings = append(warnings, w)
|
||||
}
|
||||
|
||||
if merr := b.removeBindings(ctx, iamHandle, rs.AccountId.EmailOrId, rs.Bindings); merr != nil {
|
||||
if merr := b.removeBindings(ctx, apiHandle, rs.AccountId.EmailOrId, rs.Bindings); merr != nil {
|
||||
for _, err := range merr.Errors {
|
||||
w := fmt.Sprintf("unable to delete IAM policy bindings for service account %q (WAL entry to clean-up later has been added): %v", rs.AccountId.EmailOrId, err)
|
||||
warnings = append(warnings, w)
|
||||
|
|
|
@ -137,7 +137,7 @@ func (b *backend) saveRoleSetWithNewAccount(ctx context.Context, s logical.Stora
|
|||
return nil, err
|
||||
}
|
||||
|
||||
iamHandle := iamutil.GetIamHandle(httpC, useragent.String())
|
||||
apiHandle := iamutil.GetApiHandle(httpC, useragent.String())
|
||||
|
||||
oldAccount := rs.AccountId
|
||||
oldBindings := rs.Bindings
|
||||
|
@ -162,7 +162,7 @@ func (b *backend) saveRoleSetWithNewAccount(ctx context.Context, s logical.Stora
|
|||
binds = newBinds
|
||||
rs.Bindings = newBinds
|
||||
}
|
||||
walIds, err := rs.updateIamPolicies(ctx, s, b.iamResources, iamHandle, binds)
|
||||
walIds, err := rs.updateIamPolicies(ctx, s, b.resources, apiHandle, binds)
|
||||
if err != nil {
|
||||
tryDeleteWALs(ctx, s, oldWals...)
|
||||
return nil, err
|
||||
|
@ -194,7 +194,7 @@ func (b *backend) saveRoleSetWithNewAccount(ctx context.Context, s logical.Stora
|
|||
|
||||
// Return any errors as warnings so user knows immediate cleanup failed
|
||||
warnings := make([]string, 0)
|
||||
if errs := b.removeBindings(ctx, iamHandle, oldAccount.EmailOrId, oldBindings); errs != nil {
|
||||
if errs := b.removeBindings(ctx, apiHandle, oldAccount.EmailOrId, oldBindings); errs != nil {
|
||||
warnings = make([]string, len(errs.Errors), len(errs.Errors)+2)
|
||||
for idx, err := range errs.Errors {
|
||||
warnings[idx] = fmt.Sprintf("unable to immediately delete old binding (WAL cleanup entry has been added): %v", err)
|
||||
|
@ -358,7 +358,7 @@ func (rs *RoleSet) newKeyForTokenGen(ctx context.Context, s logical.Storage, iam
|
|||
return walId, nil
|
||||
}
|
||||
|
||||
func (rs *RoleSet) updateIamPolicies(ctx context.Context, s logical.Storage, enabledIamResources iamutil.IamResourceParser, iamHandle *iamutil.IamHandle, rb ResourceBindings) ([]string, error) {
|
||||
func (rs *RoleSet) updateIamPolicies(ctx context.Context, s logical.Storage, enabledResources iamutil.ResourceParser, apiHandle *iamutil.ApiHandle, rb ResourceBindings) ([]string, error) {
|
||||
wals := make([]string, 0, len(rb))
|
||||
for rName, roles := range rb {
|
||||
walId, err := framework.PutWAL(ctx, s, walTypeIamPolicy, &walIamPolicy{
|
||||
|
@ -374,12 +374,12 @@ func (rs *RoleSet) updateIamPolicies(ctx context.Context, s logical.Storage, ena
|
|||
return wals, err
|
||||
}
|
||||
|
||||
resource, err := enabledIamResources.Parse(rName)
|
||||
resource, err := enabledResources.Parse(rName)
|
||||
if err != nil {
|
||||
return wals, err
|
||||
}
|
||||
|
||||
p, err := iamHandle.GetIamPolicy(ctx, resource)
|
||||
p, err := resource.GetIamPolicy(ctx, apiHandle)
|
||||
if err != nil {
|
||||
return wals, err
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ func (rs *RoleSet) updateIamPolicies(ctx context.Context, s logical.Storage, ena
|
|||
continue
|
||||
}
|
||||
|
||||
if _, err := iamHandle.SetIamPolicy(ctx, resource, newP); err != nil {
|
||||
if _, err := resource.SetIamPolicy(ctx, apiHandle, newP); err != nil {
|
||||
return wals, err
|
||||
}
|
||||
wals = append(wals, walId)
|
||||
|
|
|
@ -182,7 +182,7 @@ func (b *backend) serviceAccountPolicyRollback(ctx context.Context, req *logical
|
|||
}
|
||||
}
|
||||
|
||||
r, err := b.iamResources.Parse(entry.Resource)
|
||||
r, err := b.resources.Parse(entry.Resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -192,12 +192,12 @@ func (b *backend) serviceAccountPolicyRollback(ctx context.Context, req *logical
|
|||
return err
|
||||
}
|
||||
|
||||
iamHandle := iamutil.GetIamHandle(httpC, useragent.String())
|
||||
apiHandle := iamutil.GetApiHandle(httpC, useragent.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := iamHandle.GetIamPolicy(ctx, r)
|
||||
p, err := r.GetIamPolicy(ctx, apiHandle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ func (b *backend) serviceAccountPolicyRollback(ctx context.Context, req *logical
|
|||
return nil
|
||||
}
|
||||
|
||||
_, err = iamHandle.SetIamPolicy(ctx, r, newP)
|
||||
_, err = r.SetIamPolicy(ctx, apiHandle, newP)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -240,15 +240,15 @@ func (b *backend) deleteTokenGenKey(ctx context.Context, iamAdmin *iam.Service,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *backend) removeBindings(ctx context.Context, iamHandle *iamutil.IamHandle, email string, bindings ResourceBindings) (allErr *multierror.Error) {
|
||||
func (b *backend) removeBindings(ctx context.Context, apiHandle *iamutil.ApiHandle, email string, bindings ResourceBindings) (allErr *multierror.Error) {
|
||||
for resName, roles := range bindings {
|
||||
resource, err := b.iamResources.Parse(resName)
|
||||
resource, err := b.resources.Parse(resName)
|
||||
if err != nil {
|
||||
allErr = multierror.Append(allErr, errwrap.Wrapf(fmt.Sprintf("unable to delete role binding for resource '%s': {{err}}", resName), err))
|
||||
continue
|
||||
}
|
||||
|
||||
p, err := iamHandle.GetIamPolicy(ctx, resource)
|
||||
p, err := resource.GetIamPolicy(ctx, apiHandle)
|
||||
if err != nil {
|
||||
allErr = multierror.Append(allErr, errwrap.Wrapf(fmt.Sprintf("unable to delete role binding for resource '%s': {{err}}", resName), err))
|
||||
continue
|
||||
|
@ -261,7 +261,7 @@ func (b *backend) removeBindings(ctx context.Context, iamHandle *iamutil.IamHand
|
|||
if !changed {
|
||||
continue
|
||||
}
|
||||
if _, err = iamHandle.SetIamPolicy(ctx, resource, newP); err != nil {
|
||||
if _, err = resource.SetIamPolicy(ctx, apiHandle, newP); err != nil {
|
||||
allErr = multierror.Append(allErr, errwrap.Wrapf(fmt.Sprintf("unable to delete role binding for resource '%s': {{err}}", resName), err))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func pathSecretServiceAccountKey(b *backend) *framework.Path {
|
|||
Description: fmt.Sprintf(`Private key type for service account key - defaults to %s"`, privateKeyTypeJson),
|
||||
Default: privateKeyTypeJson,
|
||||
},
|
||||
"ttl": &framework.FieldSchema{
|
||||
"ttl": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "Lifetime of the service account key",
|
||||
},
|
||||
|
@ -215,6 +215,10 @@ func (b *backend) getSecretKey(ctx context.Context, s logical.Storage, rs *RoleS
|
|||
resp := b.Secret(SecretTypeKey).Response(secretD, internalD)
|
||||
resp.Secret.Renewable = true
|
||||
|
||||
resp.Secret.MaxTTL = cfg.MaxTTL
|
||||
resp.Secret.TTL = cfg.TTL
|
||||
|
||||
// If the request came with a TTL value, overwrite the config default
|
||||
if ttl > 0 {
|
||||
resp.Secret.TTL = time.Duration(ttl) * time.Second
|
||||
}
|
||||
|
|
|
@ -442,7 +442,7 @@ github.com/hashicorp/vault-plugin-secrets-alicloud
|
|||
github.com/hashicorp/vault-plugin-secrets-alicloud/clients
|
||||
# github.com/hashicorp/vault-plugin-secrets-azure v0.5.6
|
||||
github.com/hashicorp/vault-plugin-secrets-azure
|
||||
# github.com/hashicorp/vault-plugin-secrets-gcp v0.6.1
|
||||
# github.com/hashicorp/vault-plugin-secrets-gcp v0.6.2
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp/plugin
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil
|
||||
github.com/hashicorp/vault-plugin-secrets-gcp/plugin/util
|
||||
|
|
Loading…
Reference in New Issue