Skip to content

Commit c5ca7c2

Browse files
committed
add fgac samples
1 parent 54e803e commit c5ca7c2

File tree

14 files changed

+534
-16
lines changed

14 files changed

+534
-16
lines changed

google-cloud-spanner/clirr-ignored-differences.xml

+45
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,49 @@
8181
<className>com/google/cloud/spanner/connection/Connection</className>
8282
<method>com.google.spanner.v1.ResultSetStats analyzeUpdate(com.google.cloud.spanner.Statement, com.google.cloud.spanner.ReadContext$QueryAnalyzeMode)</method>
8383
</difference>
84+
<difference>
85+
<differenceType>7012</differenceType>
86+
<className>com/google/cloud/spanner/DatabaseAdminClient</className>
87+
<method>com.google.api.gax.paging.Page listDatabaseRoles(java.lang.String, java.lang.String, com.google.cloud.spanner.Options$ListOption[])</method>
88+
</difference>
89+
<difference>
90+
<differenceType>7012</differenceType>
91+
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
92+
<method>com.google.cloud.spanner.spi.v1.SpannerRpc$Paginated listDatabaseRoles(java.lang.String, int, java.lang.String)</method>
93+
</difference>
94+
<difference>
95+
<differenceType>7004</differenceType>
96+
<className>com/google/cloud/spanner/DatabaseAdminClient</className>
97+
<method>com.google.cloud.Policy getDatabaseIAMPolicy(java.lang.String, java.lang.String)</method>
98+
</difference>
99+
<difference>
100+
<differenceType>7004</differenceType>
101+
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
102+
<method>com.google.spanner.v1.Session createSession(java.lang.String, java.util.Map, java.util.Map)</method>
103+
</difference>
104+
<difference>
105+
<differenceType>7004</differenceType>
106+
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
107+
<method>java.util.List batchCreateSessions(java.lang.String, int, java.util.Map, java.util.Map)</method>
108+
</difference>
109+
<difference>
110+
<differenceType>7004</differenceType>
111+
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
112+
<method>com.google.iam.v1.Policy getDatabaseAdminIAMPolicy(java.lang.String)</method>
113+
</difference>
114+
<difference>
115+
<differenceType>7004</differenceType>
116+
<className>com/google/cloud/spanner/spi/v1/GapicSpannerRpc</className>
117+
<method>com.google.spanner.v1.Session createSession(java.lang.String, java.util.Map, java.util.Map)</method>
118+
</difference>
119+
<difference>
120+
<differenceType>7004</differenceType>
121+
<className>com/google/cloud/spanner/spi/v1/GapicSpannerRpc</className>
122+
<method>java.util.List batchCreateSessions(java.lang.String, int, java.util.Map, java.util.Map)</method>
123+
</difference>
124+
<difference>
125+
<differenceType>7004</differenceType>
126+
<className>com/google/cloud/spanner/spi/v1/GapicSpannerRpc</className>
127+
<method>com.google.iam.v1.Policy getDatabaseAdminIAMPolicy(java.lang.String)</method>
128+
</difference>
84129
</differences>

google-cloud-spanner/src/main/java/com/google/cloud/spanner/Database.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public Page<Operation> listDatabaseOperations() {
145145

146146
/** Returns the IAM {@link Policy} for this database. */
147147
public Policy getIAMPolicy() {
148-
return dbClient.getDatabaseIAMPolicy(instance(), database());
148+
return dbClient.getDatabaseIAMPolicy(instance(), database(), 1);
149149
}
150150

151151
/**

google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ OperationFuture<Void, UpdateDatabaseDdlMetadata> updateDatabaseDdl(
495495
Operation getOperation(String name);
496496

497497
/** Returns the IAM policy for the given database. */
498-
Policy getDatabaseIAMPolicy(String instanceId, String databaseId);
498+
Policy getDatabaseIAMPolicy(String instanceId, String databaseId, int version);
499499

500500
/**
501501
* Updates the IAM policy for the given database and returns the resulting policy. It is highly

google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.cloud.spanner.spi.v1.SpannerRpc.Paginated;
3030
import com.google.common.base.MoreObjects;
3131
import com.google.common.base.Preconditions;
32+
import com.google.iam.v1.GetPolicyOptions;
3233
import com.google.longrunning.Operation;
3334
import com.google.protobuf.Empty;
3435
import com.google.protobuf.FieldMask;
@@ -500,9 +501,13 @@ public Operation getOperation(String name) {
500501
}
501502

502503
@Override
503-
public Policy getDatabaseIAMPolicy(String instanceId, String databaseId) {
504+
public Policy getDatabaseIAMPolicy(String instanceId, String databaseId, int version) {
504505
final String databaseName = DatabaseId.of(projectId, instanceId, databaseId).getName();
505-
return policyMarshaller.fromPb(rpc.getDatabaseAdminIAMPolicy(databaseName));
506+
GetPolicyOptions options = null;
507+
if (version > 0) {
508+
options = GetPolicyOptions.newBuilder().setRequestedPolicyVersion(version).build();
509+
}
510+
return policyMarshaller.fromPb(rpc.getDatabaseAdminIAMPolicy(databaseName, options));
506511
}
507512

508513
@Override
@@ -524,7 +529,7 @@ public Iterable<String> testDatabaseIAMPermissions(
524529
@Override
525530
public Policy getBackupIAMPolicy(String instanceId, String backupId) {
526531
final String databaseName = BackupId.of(projectId, instanceId, backupId).getName();
527-
return policyMarshaller.fromPb(rpc.getDatabaseAdminIAMPolicy(databaseName));
532+
return policyMarshaller.fromPb(rpc.getDatabaseAdminIAMPolicy(databaseName, null));
528533
}
529534

530535
@Override

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
import com.google.common.util.concurrent.RateLimiter;
9090
import com.google.common.util.concurrent.ThreadFactoryBuilder;
9191
import com.google.iam.v1.GetIamPolicyRequest;
92+
import com.google.iam.v1.GetPolicyOptions;
9293
import com.google.iam.v1.Policy;
9394
import com.google.iam.v1.SetIamPolicyRequest;
9495
import com.google.iam.v1.TestIamPermissionsRequest;
@@ -1695,10 +1696,13 @@ public PartitionResponse partitionRead(
16951696
}
16961697

16971698
@Override
1698-
public Policy getDatabaseAdminIAMPolicy(String resource) {
1699+
public Policy getDatabaseAdminIAMPolicy(String resource, @Nullable GetPolicyOptions options) {
16991700
acquireAdministrativeRequestsRateLimiter();
1700-
final GetIamPolicyRequest request =
1701-
GetIamPolicyRequest.newBuilder().setResource(resource).build();
1701+
GetIamPolicyRequest.Builder builder = GetIamPolicyRequest.newBuilder().setResource(resource);
1702+
if (options != null) {
1703+
builder.setOptions(options);
1704+
}
1705+
final GetIamPolicyRequest request = builder.build();
17021706
final GrpcCallContext context =
17031707
newCallContext(null, resource, request, DatabaseAdminGrpc.getGetIamPolicyMethod());
17041708
return runWithRetryOnAdministrativeRequestsExceeded(

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.cloud.spanner.admin.database.v1.stub.DatabaseAdminStub;
2929
import com.google.cloud.spanner.admin.instance.v1.stub.InstanceAdminStub;
3030
import com.google.common.collect.ImmutableList;
31+
import com.google.iam.v1.GetPolicyOptions;
3132
import com.google.iam.v1.Policy;
3233
import com.google.iam.v1.TestIamPermissionsResponse;
3334
import com.google.longrunning.Operation;
@@ -328,7 +329,7 @@ PartitionResponse partitionRead(PartitionReadRequest request, @Nullable Map<Opti
328329
throws SpannerException;
329330

330331
/** Gets the IAM policy for the given resource using the {@link DatabaseAdminStub}. */
331-
Policy getDatabaseAdminIAMPolicy(String resource);
332+
Policy getDatabaseAdminIAMPolicy(String resource, @Nullable GetPolicyOptions options);
332333

333334
/**
334335
* Updates the IAM policy for the given resource using the {@link DatabaseAdminStub}. It is highly

google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ public void listDatabaseRolesErrorWithToken() {
358358

359359
@Test
360360
public void getDatabaseIAMPolicy() {
361-
when(rpc.getDatabaseAdminIAMPolicy(DB_NAME))
361+
when(rpc.getDatabaseAdminIAMPolicy(DB_NAME, null))
362362
.thenReturn(
363363
Policy.newBuilder()
364364
.addBindings(
@@ -367,11 +367,11 @@ public void getDatabaseIAMPolicy() {
367367
.setRole("roles/viewer")
368368
.build())
369369
.build());
370-
com.google.cloud.Policy policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID);
370+
com.google.cloud.Policy policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID, 1);
371371
assertThat(policy.getBindings())
372372
.containsExactly(Role.viewer(), Sets.newHashSet(Identity.user("[email protected]")));
373373

374-
when(rpc.getDatabaseAdminIAMPolicy(DB_NAME))
374+
when(rpc.getDatabaseAdminIAMPolicy(DB_NAME, null))
375375
.thenReturn(
376376
Policy.newBuilder()
377377
.addBindings(
@@ -380,7 +380,7 @@ public void getDatabaseIAMPolicy() {
380380
.setRole("roles/viewer")
381381
.build())
382382
.build());
383-
policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID);
383+
policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID, 1);
384384
assertThat(policy.getBindings())
385385
.containsExactly(
386386
Role.viewer(),

google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -755,13 +755,13 @@ public void backupListBackupOperations()
755755

756756
@Test
757757
public void getAndSetIAMPolicy() {
758-
Policy policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID);
758+
Policy policy = client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID, 1);
759759
assertThat(policy).isEqualTo(Policy.newBuilder().build());
760760
Policy newPolicy =
761761
Policy.newBuilder().addIdentity(Role.editor(), Identity.user("[email protected]")).build();
762762
Policy returnedPolicy = client.setDatabaseIAMPolicy(INSTANCE_ID, DB_ID, newPolicy);
763763
assertThat(returnedPolicy).isEqualTo(newPolicy);
764-
assertThat(client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID)).isEqualTo(newPolicy);
764+
assertThat(client.getDatabaseIAMPolicy(INSTANCE_ID, DB_ID, 1)).isEqualTo(newPolicy);
765765
}
766766

767767
@Test

google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public void getIAMPolicy() {
184184
new Database(
185185
DatabaseId.of("test-project", "test-instance", "test-database"), State.READY, dbClient);
186186
database.getIAMPolicy();
187-
verify(dbClient).getDatabaseIAMPolicy("test-instance", "test-database");
187+
verify(dbClient).getDatabaseIAMPolicy("test-instance", "test-database", 1);
188188
}
189189

190190
@Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2022 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_add_new_database_role]
20+
21+
import com.google.api.gax.longrunning.OperationFuture;
22+
import com.google.cloud.spanner.DatabaseAdminClient;
23+
import com.google.cloud.spanner.Spanner;
24+
import com.google.cloud.spanner.SpannerOptions;
25+
import com.google.common.collect.ImmutableList;
26+
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
27+
import java.util.concurrent.ExecutionException;
28+
29+
public class AddNewRoleSample {
30+
static void addNewRole() throws InterruptedException, ExecutionException {
31+
// TODO(developer): Replace these variables before running the sample.
32+
String projectId = "my-project";
33+
String instanceId = "my-instance";
34+
String databaseId = "my-database";
35+
addNewRole(projectId, instanceId, databaseId);
36+
}
37+
38+
static void addNewRole(String projectId, String instanceId, String databaseId)
39+
throws InterruptedException, ExecutionException {
40+
try (Spanner spanner =
41+
SpannerOptions.newBuilder()
42+
.setProjectId(projectId)
43+
.build()
44+
.getService()) {
45+
final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient();
46+
OperationFuture<Void, UpdateDatabaseDdlMetadata> operation =
47+
adminClient.updateDatabaseDdl(
48+
instanceId,
49+
databaseId,
50+
ImmutableList.of(
51+
"CREATE ROLE parent",
52+
"GRANT SELECT ON TABLE Albums TO ROLE parent",
53+
"CREATE ROLE child",
54+
"GRANT ROLE parent TO ROLE child"),
55+
null);
56+
57+
// Wait for the operation to finish.
58+
// This will throw an ExecutionException if the operation fails.
59+
operation.get();
60+
System.out.println("Successfully added parent and child roles");
61+
62+
// Delete role and membership.
63+
operation =
64+
adminClient.updateDatabaseDdl(
65+
instanceId,
66+
databaseId,
67+
ImmutableList.of("REVOKE ROLE parent FROM ROLE child", "DROP ROLE child"),
68+
null);
69+
// Wait for the operation to finish.
70+
// This will throw an ExecutionException if the operation fails.
71+
operation.get();
72+
System.out.println("Successfully deleted chile role");
73+
}
74+
}
75+
}
76+
// [END spanner_add_new_database_role]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2022 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_enable_fine_grained_access]
20+
21+
import com.google.cloud.Binding;
22+
import com.google.cloud.Condition;
23+
import com.google.cloud.Policy;
24+
import com.google.cloud.spanner.DatabaseAdminClient;
25+
import com.google.cloud.spanner.Spanner;
26+
import com.google.cloud.spanner.SpannerOptions;
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
30+
public class EnableFineGrainedAccess {
31+
static void enableFineGrainedAccess() {
32+
// TODO(developer): Replace these variables before running the sample.
33+
String projectId = "my-project";
34+
String instanceId = "my-instance";
35+
String databaseId = "my-database";
36+
String iamMember = "my-member";
37+
String databaseRole = "my-role";
38+
String conditionTitle = "my-title";
39+
enableFineGrainedAccess(
40+
projectId, instanceId, databaseId, iamMember, databaseRole, conditionTitle);
41+
}
42+
43+
static void enableFineGrainedAccess(
44+
String projectId,
45+
String instanceId,
46+
String databaseId,
47+
String iamMember,
48+
String databaseRole,
49+
String title) {
50+
try (Spanner spanner =
51+
SpannerOptions.newBuilder()
52+
.setProjectId(projectId)
53+
.build()
54+
.getService()) {
55+
final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient();
56+
Policy policy = adminClient.getDatabaseIAMPolicy(instanceId, databaseId, 3);
57+
int policyVersion = policy.getVersion();
58+
if (policy.getVersion() < 3) {
59+
policyVersion = 3;
60+
}
61+
List<String> members = new ArrayList<>();
62+
members.add(iamMember);
63+
List<Binding> bindings = new ArrayList<>();
64+
bindings.addAll(policy.getBindingsList());
65+
66+
bindings.add(
67+
Binding.newBuilder()
68+
.setRole("roles/spanner.fineGrainedAccessUser")
69+
.setMembers(members)
70+
.build());
71+
72+
bindings.add(
73+
Binding.newBuilder()
74+
.setRole("roles/spanner.databaseRoleUser")
75+
.setCondition(
76+
Condition.newBuilder()
77+
.setDescription(title)
78+
.setExpression(
79+
String.format(
80+
"resource.name.endsWith(\"/databaseRoles/%s\")", databaseRole))
81+
.setTitle(title)
82+
.build())
83+
.setMembers(members)
84+
.build());
85+
86+
Policy policyWithConditions =
87+
Policy.newBuilder()
88+
.setVersion(policyVersion)
89+
.setEtag(policy.getEtag())
90+
.setBindings(bindings)
91+
.build();
92+
Policy response =
93+
adminClient.setDatabaseIAMPolicy(instanceId, databaseId, policyWithConditions);
94+
System.out.println(
95+
String.format(
96+
"Successfully enabled fined grained access, created policy with version %d",
97+
response.getVersion()));
98+
}
99+
}
100+
}
101+
// [END spanner_enable_fine_grained_access]

0 commit comments

Comments
 (0)