Skip to content

Commit 77969e3

Browse files
feat(spanner): add samples for fine grained access control (#2172)
* feat(spanner): add samples for fine grained access control * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix sample checkstyles * incorporate review comment * incorporate requested changes * incorporate requested changes * fix checkstyle * incorporate review comments * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * refactoring * remove role check & exceptions Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent ff8c425 commit 77969e3

File tree

6 files changed

+442
-0
lines changed

6 files changed

+442
-0
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
243243
| Database Operations | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/DatabaseOperations.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/DatabaseOperations.java) |
244244
| Instance Operations | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/InstanceOperations.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/InstanceOperations.java) |
245245
| Native Image Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/NativeImageSpannerSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/NativeImageSpannerSample.java) |
246+
| Add And Drop Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java) |
246247
| Add Json Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java) |
247248
| Add Jsonb Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java) |
248249
| Add Numeric Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java) |
@@ -267,10 +268,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
267268
| Custom Timeout And Retry Settings Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CustomTimeoutAndRetrySettingsExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CustomTimeoutAndRetrySettingsExample.java) |
268269
| Delete Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java) |
269270
| Delete Using Dml Returning Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DeleteUsingDmlReturningSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DeleteUsingDmlReturningSample.java) |
271+
| Enable Fine Grained Access | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java) |
270272
| Get Commit Stats Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/GetCommitStatsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/GetCommitStatsSample.java) |
271273
| Get Database Ddl Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java) |
272274
| Get Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) |
273275
| Insert Using Dml Returning Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/InsertUsingDmlReturningSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/InsertUsingDmlReturningSample.java) |
276+
| List Database Roles | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java) |
274277
| List Databases Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) |
275278
| List Instance Config Operations Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java) |
276279
| List Instance Configs Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) |
@@ -291,6 +294,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
291294
| Query With Jsonb Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithJsonbParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithJsonbParameterSample.java) |
292295
| Query With Numeric Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) |
293296
| Quickstart Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QuickstartSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QuickstartSample.java) |
297+
| Read Data With Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ReadDataWithDatabaseRole.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ReadDataWithDatabaseRole.java) |
294298
| Restore Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java) |
295299
| Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/SpannerSample.java) |
296300
| Statement Timeout Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/StatementTimeoutExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/StatementTimeoutExample.java) |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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_and_drop_database_role]
20+
import com.google.api.gax.longrunning.OperationFuture;
21+
import com.google.cloud.spanner.DatabaseAdminClient;
22+
import com.google.cloud.spanner.Spanner;
23+
import com.google.cloud.spanner.SpannerOptions;
24+
import com.google.common.collect.ImmutableList;
25+
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
26+
import java.util.concurrent.ExecutionException;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.TimeoutException;
29+
30+
public class AddAndDropDatabaseRole {
31+
32+
static void addAndDropDatabaseRole() {
33+
// TODO(developer): Replace these variables before running the sample.
34+
String projectId = "my-project";
35+
String instanceId = "my-instance";
36+
String databaseId = "my-database";
37+
String parentRole = "my-new-parent-role";
38+
String childRole = "my-new-child-role";
39+
addAndDropDatabaseRole(projectId, instanceId, databaseId, parentRole, childRole);
40+
}
41+
42+
static void addAndDropDatabaseRole(
43+
String projectId, String instanceId, String databaseId, String parentRole, String childRole) {
44+
try (Spanner spanner =
45+
SpannerOptions.newBuilder()
46+
.setProjectId(projectId)
47+
.build()
48+
.getService()) {
49+
final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient();
50+
OperationFuture<Void, UpdateDatabaseDdlMetadata> operation =
51+
adminClient.updateDatabaseDdl(
52+
instanceId,
53+
databaseId,
54+
ImmutableList.of(
55+
"CREATE ROLE " + parentRole,
56+
"GRANT SELECT ON TABLE Albums TO ROLE " + parentRole,
57+
"CREATE ROLE " + childRole,
58+
"GRANT ROLE " + parentRole + " TO ROLE " + childRole),
59+
null);
60+
try {
61+
System.out.println("Waiting for role create operation to complete...");
62+
operation.get(5, TimeUnit.MINUTES);
63+
System.out.printf(
64+
"Created roles %s and %s and granted privileges%n", parentRole, childRole);
65+
// Delete role and membership.
66+
operation =
67+
adminClient.updateDatabaseDdl(
68+
instanceId,
69+
databaseId,
70+
ImmutableList.of(
71+
"REVOKE ROLE " + parentRole + " FROM ROLE " + childRole,
72+
"DROP ROLE " + childRole),
73+
null);
74+
System.out.println("Waiting for role revoke & drop operation to complete...");
75+
operation.get(5, TimeUnit.MINUTES);
76+
System.out.printf("Revoked privileges and dropped role %s%n", childRole);
77+
} catch (ExecutionException | TimeoutException e) {
78+
System.out.printf(
79+
"Error: AddAndDropDatabaseRole failed with error message %s\n", e.getMessage());
80+
e.printStackTrace();
81+
} catch (InterruptedException e) {
82+
System.out.println(
83+
"Error: Waiting for AddAndDropDatabaseRole operation to finish was interrupted");
84+
}
85+
}
86+
}
87+
}
88+
// [END spanner_add_and_drop_database_role]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
import com.google.cloud.Binding;
21+
import com.google.cloud.Condition;
22+
import com.google.cloud.Policy;
23+
import com.google.cloud.spanner.DatabaseAdminClient;
24+
import com.google.cloud.spanner.Spanner;
25+
import com.google.cloud.spanner.SpannerOptions;
26+
import com.google.common.collect.ImmutableList;
27+
28+
public class EnableFineGrainedAccess {
29+
30+
static void enableFineGrainedAccess() {
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+
String iamMember = "user:alice@example.com";
36+
String role = "my-role";
37+
String title = "my-condition-title";
38+
enableFineGrainedAccess(projectId, instanceId, databaseId, iamMember, title, role);
39+
}
40+
41+
static void enableFineGrainedAccess(
42+
String projectId,
43+
String instanceId,
44+
String databaseId,
45+
String iamMember,
46+
String title,
47+
String role) {
48+
try (Spanner spanner =
49+
SpannerOptions.newBuilder()
50+
.setProjectId(projectId)
51+
.build()
52+
.getService()) {
53+
final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient();
54+
Policy policy = adminClient.getDatabaseIAMPolicy(instanceId, databaseId, 3);
55+
int policyVersion = policy.getVersion();
56+
// The policy in the response from getDatabaseIAMPolicy might use the policy version
57+
// that you specified, or it might use a lower policy version. For example, if you
58+
// specify version 3, but the policy has no conditional role bindings, the response
59+
// uses version 1. Valid values are 0, 1, and 3.
60+
if (policy.getVersion() < 3) {
61+
// conditional role bindings work with policy version 3
62+
policyVersion = 3;
63+
}
64+
65+
Binding binding1 =
66+
Binding.newBuilder()
67+
.setRole("roles/spanner.fineGrainedAccessUser")
68+
.setMembers(ImmutableList.of(iamMember))
69+
.build();
70+
71+
Binding binding2 =
72+
Binding.newBuilder()
73+
.setRole("roles/spanner.databaseRoleUser")
74+
.setCondition(
75+
Condition.newBuilder()
76+
.setDescription(title)
77+
.setExpression(
78+
String.format("resource.name.endsWith(\"/databaseRoles/%s\")", role))
79+
.setTitle(title)
80+
.build())
81+
.setMembers(ImmutableList.of(iamMember))
82+
.build();
83+
ImmutableList<Binding> bindings =
84+
ImmutableList.<Binding>builder()
85+
.addAll(policy.getBindingsList())
86+
.add(binding1)
87+
.add(binding2)
88+
.build();
89+
Policy policyWithConditions =
90+
Policy.newBuilder()
91+
.setVersion(policyVersion)
92+
.setEtag(policy.getEtag())
93+
.setBindings(bindings)
94+
.build();
95+
Policy response =
96+
adminClient.setDatabaseIAMPolicy(instanceId, databaseId, policyWithConditions);
97+
System.out.printf(
98+
"Enabled fine-grained access in IAM with version %d%n", response.getVersion());
99+
}
100+
}
101+
}
102+
// [END spanner_enable_fine_grained_access]

0 commit comments

Comments
 (0)