From 0538eeee243bf5849620c9b864170fc61f866398 Mon Sep 17 00:00:00 2001 From: trollyxia Date: Mon, 11 Mar 2024 15:31:08 +0000 Subject: [PATCH] feat: Add AuthorizedView IAM Change-Id: I9781e0882f1b152228edb276f12284d5ccf64315 --- bigtable/admin.go | 5 +++ bigtable/integration_test.go | 77 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/bigtable/admin.go b/bigtable/admin.go index 7c692342037d..f9c9892449e5 100644 --- a/bigtable/admin.go +++ b/bigtable/admin.go @@ -885,6 +885,11 @@ func (ac *AdminClient) BackupIAM(cluster, backup string) *iam.Handle { return iam.InternalNewHandleGRPCClient(ac.tClient, ac.backupPath(cluster, ac.instance, backup)) } +// AuthorizedViewIAM creates an IAM Handle specific to a given Table and AuthorizedView. +func (ac *AdminClient) AuthorizedViewIAM(table, authorizedView string) *iam.Handle { + return iam.InternalNewHandleGRPCClient(ac.tClient, ac.authorizedViewPath(table, authorizedView)) +} + const instanceAdminAddr = "bigtableadmin.googleapis.com:443" const mtlsInstanceAdminAddr = "bigtableadmin.mtls.googleapis.com:443" diff --git a/bigtable/integration_test.go b/bigtable/integration_test.go index a84ee4d57a05..4310c5ba1727 100644 --- a/bigtable/integration_test.go +++ b/bigtable/integration_test.go @@ -1994,6 +1994,83 @@ func TestIntegration_BackupIAM(t *testing.T) { } } +func TestIntegration_AuthorizedViewIAM(t *testing.T) { + testEnv, err := NewIntegrationEnv() + if err != nil { + t.Fatalf("IntegrationEnv: %v", err) + } + defer testEnv.Close() + + if !testEnv.Config().UseProd { + t.Skip("emulator doesn't support IAM Policy creation") + } + timeout := 5 * time.Minute + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + adminClient, err := testEnv.NewAdminClient() + if err != nil { + t.Fatalf("NewAdminClient: %v", err) + } + defer adminClient.Close() + + table := testEnv.Config().Table + + defer deleteTable(ctx, t, adminClient, table) + if err := adminClient.CreateTable(ctx, table); err != nil { + t.Fatalf("Creating table: %v", err) + } + + // Create authorized view. + opts := &uid.Options{Sep: '_'} + authorizedViewUUID := uid.NewSpace("authorizedView", opts) + authorizedView := authorizedViewUUID.New() + + defer adminClient.DeleteAuthorizedView(ctx, table, authorizedView) + + if err = adminClient.CreateAuthorizedView(ctx, &AuthorizedViewConf{ + TableID: table, + AuthorizedViewID: authorizedView, + AuthorizedViewTypeConf: AuthorizedViewTypeConf{ + AuthorizedViewType: AuthorizedViewTypeSubsetView, + SubsetView: &SubsetViewConf{}, + }, + DeletionProtection: Unprotected, + }); err != nil { + t.Fatalf("Creating authorizedView: %v", err) + } + iamHandle := adminClient.AuthorizedViewIAM(table, authorizedView) + // Get authorized view policy. + p, err := iamHandle.Policy(ctx) + if err != nil { + t.Errorf("iamHandle.Policy: %v", err) + } + // The resource is new, so the policy should be empty. + if got := p.Roles(); len(got) > 0 { + t.Errorf("got roles %v, want none", got) + } + // Set authorized view policy. + member := "domain:google.com" + // Add a member, set the policy, then check that the member is present. + p.Add(member, iam.Viewer) + if err = iamHandle.SetPolicy(ctx, p); err != nil { + t.Errorf("iamHandle.SetPolicy: %v", err) + } + p, err = iamHandle.Policy(ctx) + if err != nil { + t.Errorf("iamHandle.Policy: %v", err) + } + if got, want := p.Members(iam.Viewer), []string{member}; !testutil.Equal(got, want) { + t.Errorf("iamHandle.Policy: got %v, want %v", got, want) + } + // Test authorized view permissions. + permissions := []string{"bigtable.authorizedViews.get", "bigtable.authorizedViews.update"} + _, err = iamHandle.TestPermissions(ctx, permissions) + if err != nil { + t.Errorf("iamHandle.TestPermissions: %v", err) + } +} + func TestIntegration_AdminCreateInstance(t *testing.T) { if instanceToCreate == "" { t.Skip("instanceToCreate not set, skipping instance creation testing")