Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bigquery): support group account type in bigquery provider #132

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions plugins/providers/bigquery/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,40 +98,48 @@ func (c *bigQueryClient) GetTables(ctx context.Context, datasetID string) ([]*Ta
return results, nil
}

func (c *bigQueryClient) GrantDatasetAccess(ctx context.Context, d *Dataset, user, role string) error {
func (c *bigQueryClient) GrantDatasetAccess(ctx context.Context, d *Dataset, accountType, accountID, role string) error {
dataset := c.client.Dataset(d.DatasetID)
metadata, err := dataset.Metadata(ctx)
if err != nil {
return err
}

for _, a := range metadata.Access {
if a.Entity == user && string(a.Role) == role {
if a.Entity == accountID && string(a.Role) == role {
return ErrPermissionAlreadyExists
}
}
entityType := bq.UserEmailEntity
if accountType == AccountTypeGroup {
entityType = bq.GroupEmailEntity
}
update := bq.DatasetMetadataToUpdate{
Access: append(metadata.Access, &bq.AccessEntry{
Role: bq.AccessRole(role),
EntityType: bq.UserEmailEntity,
Entity: user,
EntityType: entityType,
Entity: accountID,
}),
}

_, err = dataset.Update(ctx, update, metadata.ETag)
return err
}

func (c *bigQueryClient) RevokeDatasetAccess(ctx context.Context, d *Dataset, user, role string) error {
func (c *bigQueryClient) RevokeDatasetAccess(ctx context.Context, d *Dataset, accountType, accountID, role string) error {
dataset := c.client.Dataset(d.DatasetID)
metadata, err := dataset.Metadata(ctx)
if err != nil {
return err
}

entityType := bq.UserEmailEntity
if accountType == AccountTypeGroup {
entityType = bq.GroupEmailEntity
}
remainingAccessEntries := []*bq.AccessEntry{}
for _, a := range metadata.Access {
if a.Entity == user && string(a.Role) == role {
if a.EntityType == entityType && a.Entity == accountID && string(a.Role) == role {
continue
}
remainingAccessEntries = append(remainingAccessEntries, a)
Expand Down
1 change: 1 addition & 0 deletions plugins/providers/bigquery/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (

AccountTypeUser = "user"
AccountTypeServiceAccount = "serviceAccount"
AccountTypeGroup = "group"
)

// Credentials is the authentication configuration used by the bigquery client
Expand Down
46 changes: 24 additions & 22 deletions plugins/providers/bigquery/mocks/BigQueryClient.go

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

9 changes: 5 additions & 4 deletions plugins/providers/bigquery/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ var (
type BigQueryClient interface {
GetDatasets(context.Context) ([]*Dataset, error)
GetTables(ctx context.Context, datasetID string) ([]*Table, error)
GrantDatasetAccess(ctx context.Context, d *Dataset, user, role string) error
RevokeDatasetAccess(ctx context.Context, d *Dataset, user, role string) error
GrantDatasetAccess(ctx context.Context, d *Dataset, accountType, accountID, role string) error
RevokeDatasetAccess(ctx context.Context, d *Dataset, accountType, accountID, role string) error
GrantTableAccess(ctx context.Context, t *Table, accountType, accountID, role string) error
RevokeTableAccess(ctx context.Context, t *Table, accountType, accountID, role string) error
ListAccess(ctx context.Context, resources []*domain.Resource) (domain.MapResourceAccess, error)
Expand Down Expand Up @@ -222,7 +222,7 @@ func (p *Provider) GrantAccess(ctx context.Context, pc *domain.ProviderConfig, a
}

for _, p := range permissions {
if err := bqClient.GrantDatasetAccess(ctx, d, a.AccountID, string(p)); err != nil {
if err := bqClient.GrantDatasetAccess(ctx, d, a.AccountType, a.AccountID, string(p)); err != nil {
if errors.Is(err, ErrPermissionAlreadyExists) {
return nil
}
Expand Down Expand Up @@ -274,7 +274,7 @@ func (p *Provider) RevokeAccess(ctx context.Context, pc *domain.ProviderConfig,
}

for _, p := range permissions {
if err := bqClient.RevokeDatasetAccess(ctx, d, a.AccountID, string(p)); err != nil {
if err := bqClient.RevokeDatasetAccess(ctx, d, a.AccountType, a.AccountID, string(p)); err != nil {
if errors.Is(err, ErrPermissionNotFound) {
return nil
}
Expand Down Expand Up @@ -312,6 +312,7 @@ func (p *Provider) GetAccountTypes() []string {
return []string{
AccountTypeUser,
AccountTypeServiceAccount,
AccountTypeGroup,
}
}

Expand Down
18 changes: 13 additions & 5 deletions plugins/providers/bigquery/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,9 @@ func TestGrantAccess(t *testing.T) {
ServiceAccountKey: base64.StdEncoding.EncodeToString([]byte("service-account-key-json")),
ResourceName: "projects/resource-name",
}
client.On("GrantDatasetAccess", mock.Anything, mock.Anything, expectedAccountID, mock.Anything).Return(expectedError).Once()
client.EXPECT().
GrantDatasetAccess(mock.Anything, mock.Anything, expectedAccountType, expectedAccountID, mock.Anything).
Return(expectedError).Once()

pc := &domain.ProviderConfig{
Type: "bigquery",
Expand Down Expand Up @@ -599,7 +601,9 @@ func TestGrantAccess(t *testing.T) {
ServiceAccountKey: base64.StdEncoding.EncodeToString([]byte("service-account-key-json")),
ResourceName: "projects/resource-name",
}
client.On("GrantDatasetAccess", mock.Anything, mock.Anything, expectedAccountID, mock.Anything).Return(bigquery.ErrPermissionAlreadyExists).Once()
client.EXPECT().
GrantDatasetAccess(mock.Anything, mock.Anything, expectedAccountType, expectedAccountID, mock.Anything).
Return(bigquery.ErrPermissionAlreadyExists).Once()

pc := &domain.ProviderConfig{
Type: "bigquery",
Expand Down Expand Up @@ -807,7 +811,9 @@ func TestRevokeAccess(t *testing.T) {
ServiceAccountKey: base64.StdEncoding.EncodeToString([]byte("service-account-key-json")),
ResourceName: "projects/resource-name",
}
client.On("RevokeDatasetAccess", mock.Anything, mock.Anything, expectedAccountID, mock.Anything).Return(expectedError).Once()
client.EXPECT().
RevokeDatasetAccess(mock.Anything, mock.Anything, expectedAccountType, expectedAccountID, mock.Anything).
Return(expectedError).Once()

pc := &domain.ProviderConfig{
Type: "bigquery",
Expand Down Expand Up @@ -859,7 +865,9 @@ func TestRevokeAccess(t *testing.T) {
ServiceAccountKey: base64.StdEncoding.EncodeToString([]byte("service-account-key-json")),
ResourceName: "projects/resource-name",
}
client.On("RevokeDatasetAccess", mock.Anything, mock.Anything, expectedAccountID, mock.Anything).Return(bigquery.ErrPermissionNotFound).Once()
client.EXPECT().
RevokeDatasetAccess(mock.Anything, mock.Anything, expectedAccountType, expectedAccountID, mock.Anything).
Return(bigquery.ErrPermissionNotFound).Once()

pc := &domain.ProviderConfig{
Type: "bigquery",
Expand Down Expand Up @@ -957,7 +965,7 @@ func TestRevokeAccess(t *testing.T) {
func TestGetAccountTypes(t *testing.T) {
t.Run("should return the supported account types \"user\" and \"serviceAccount\"", func(t *testing.T) {
p := initProvider()
expectedAccountTypes := []string{"user", "serviceAccount"}
expectedAccountTypes := []string{"user", "serviceAccount", "group"}

actualAccountTypes := p.GetAccountTypes()

Expand Down
Loading