Skip to content

Commit

Permalink
feat(gcs): support import grants for gcs provider (#360)
Browse files Browse the repository at this point in the history
* feat(gcs): support import grants for gcs provider

* refactor(gcs): use projectID value from struct field and remove from GetBuckets' param

* refactor(gcs): refactor repeated logic to retrieve gcs client

* refactor(gcs): improve code readability
  • Loading branch information
rahmatrhd authored Feb 16, 2023
1 parent a4b0c5d commit 3a88ce9
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 72 deletions.
72 changes: 63 additions & 9 deletions plugins/providers/gcs/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ package gcs
import (
"context"
"fmt"
"strings"

"cloud.google.com/go/iam"
"cloud.google.com/go/storage"
"github.com/odpf/guardian/domain"
"github.com/odpf/guardian/utils"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
)

//go:generate mockery --name=GCSClient --exported --with-expecter
type GCSClient interface {
GetBuckets(ctx context.Context, projectID string) ([]*Bucket, error)
GrantBucketAccess(ctx context.Context, b Bucket, identity string, roleName iam.RoleName) error
RevokeBucketAccess(ctx context.Context, b Bucket, identity string, roleName iam.RoleName) error
}
var (
excludedAccountTypesOnImport = []string{"allUsers", "allAuthenticatedUsers", "projectOwner", "projectEditor", "projectViewer"}
)

type gcsClient struct {
client *storage.Client
Expand All @@ -34,10 +34,10 @@ func newGCSClient(projectID string, credentialsJSON []byte) (*gcsClient, error)
}, nil
}

// GetBuckets returns all buckets within a given project
func (c *gcsClient) GetBuckets(ctx context.Context, projectID string) ([]*Bucket, error) {
// GetBuckets returns all buckets in the project
func (c *gcsClient) GetBuckets(ctx context.Context) ([]*Bucket, error) {
var result []*Bucket
it := c.client.Buckets(ctx, projectID)
it := c.client.Buckets(ctx, c.projectID)
for {
battrs, err := it.Next()
if err == iterator.Done {
Expand Down Expand Up @@ -84,3 +84,57 @@ func (c *gcsClient) RevokeBucketAccess(ctx context.Context, b Bucket, identity s

return nil
}

func (c *gcsClient) ListAccess(ctx context.Context, resources []*domain.Resource) (domain.MapResourceAccess, error) {
result := make(domain.MapResourceAccess)

for _, resource := range resources {
var accessEntries []domain.AccessEntry

bucket := c.client.Bucket(resource.URN)
policy, err := bucket.IAM().Policy(ctx)
if err != nil {
return nil, fmt.Errorf("Bucket(%q).IAM().Policy: %w", resource.URN, err)
}

for _, role := range policy.Roles() {
for _, member := range policy.Members(role) {
accountType, accountID, err := parseMember(member)
if err != nil {
return nil, err
}

// exclude unsupported account types
if utils.ContainsString(excludedAccountTypesOnImport, accountType) {
continue
}

accessEntries = append(accessEntries, domain.AccessEntry{
Permission: string(role),
AccountID: accountID,
AccountType: accountType,
})
}
}

if accessEntries != nil {
result[resource.URN] = accessEntries
}
}

return result, nil
}

func parseMember(member string) (accountType, accountID string, err error) {
m := strings.Split(member, ":")
if len(m) == 0 || len(m) > 2 {
return "", "", fmt.Errorf("invalid bucket access member signature %q", member)
}

if len(m) == 2 {
accountID = m[1]
}
accountType = m[0]

return accountType, accountID, nil
}
41 changes: 36 additions & 5 deletions plugins/providers/gcs/mocks/Crypto.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

137 changes: 113 additions & 24 deletions plugins/providers/gcs/mocks/GCSClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3a88ce9

Please sign in to comment.