This page explains how to configure fine-grained access control for Spanner databases.
To learn about fine-grained access control, see About fine-grained access control.
Configuring fine-grained access control involves the following steps:
Fine-grained access control users must then specify a database role to perform queries, DML, or row operations against the database.
Before you begin
Ensure that each principal who is to be a fine-grained access control user is granted
the Cloud Spanner Viewer
IAM role (roles/spanner.viewer
).
This role is recommended at the project level for users who must interact with
Spanner resources in the Google Cloud console.
For instructions, see Grant permissions to principals.
Create database roles and grant privileges
A database role is a collection of fine-grained access privileges. You can create up to 100 database roles for each database.
Decide on roles and role hierarchies in your database and encode them in DDL. As with other schema changes in Spanner, we strongly recommend issuing schema changes in a batch rather than separately. For more information, see Limit the frequency of schema updates.
Console
To create a database role and grant fine-grained access privileges to it, follow these steps:
Go to the Instances page in the Google Cloud console.
Select the instance containing the database for which you want to add the role.
Select the database.
On the Overview page, click Spanner Studio.
On the Spanner Studio page, for each database role that you want to create and grant privileges to, follow these steps:
To create the role, enter the following statement:
CREATE ROLE ROLE_NAME;
Don't click Submit yet.
To grant privileges to the role, enter a
GRANT
statement on the next line after theCREATE ROLE
statement.For syntax details for the
GRANT
statement, see GoogleSQL data definition language. For information about privileges, see Fine-grained access control privileges.For example, to grant
SELECT
,INSERT
, andUPDATE
on tablesemployees
andcontractors
to the database rolehr_manager
, enter the following statement:GoogleSQL
GRANT SELECT, INSERT, UPDATE ON TABLE employees, contractors TO ROLE hr_manager;
PostgreSQL
GRANT SELECT, INSERT, UPDATE ON TABLE employees, contractors TO hr_manager;
You can use a DDL template for the
GRANT
statement. In the Explorer pane, navigate to the role for which you want to grant privileges. Click View actions and select the type of privilege you want to grant access for this role. TheGRANT
template statement populates in a new editor tab.
Click Submit.
If there are errors in your DDL, the Google Cloud console returns an error.
gcloud
To create a database role and grant fine-grained access privileges to it,
use the gcloud spanner databases ddl update
command with CREATE ROLE
and GRANT
statements.
For syntax details on the CREATE ROLE
and GRANT
statements, see
GoogleSQL data definition language.
For example, use the following command to create a database role and grant privileges to it on one or more tables.
GoogleSQL
gcloud spanner databases ddl update DATABASE_NAME --instance=INSTANCE_NAME \ --ddl='CREATE ROLE ROLE_NAME; GRANT PRIVILEGES ON TABLE TABLES TO ROLE ROLE_NAME;'
PostgreSQL
gcloud spanner databases ddl update DATABASE_NAME --instance=INSTANCE_NAME \ --ddl='CREATE ROLE ROLE_NAME; GRANT PRIVILEGES ON TABLE TABLES TO ROLE_NAME;'
Replace the following:
PRIVILEGES
is a comma-delimited list of fine-grained access control privileges. For information about privileges, see Fine-grained access control privileges.TABLES
is a comma-delimited list of tables.
For example, to grant SELECT
,
INSERT
, and UPDATE
on the employees
and contractors
tables to the
database role hr_analyst
in the database hrdb1
in the instance hr
, enter
the following statement:
GoogleSQL
gcloud spanner databases ddl update hrdb1 --instance=hr \ --ddl='CREATE ROLE hr_analyst; GRANT SELECT, INSERT, UPDATE ON TABLE employees, contractors TO ROLE hr_analyst;'
PostgreSQL
gcloud spanner databases ddl update hrdb1 --instance=hr \ --ddl='CREATE ROLE hr_analyst; GRANT SELECT, INSERT, UPDATE ON TABLE employees, contractors TO hr_analyst;'
Client libraries
These code samples both create and drop a database role.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Create a hierarchy of roles with inheritance
You can create a hierarchy of database roles by granting one database role to another. Child roles (known as member roles) inherit privileges from the parent.
To grant a database role to another database role, use the following statement:
GoogleSQL
GRANT ROLE role1 TO ROLE role2;
PostgreSQL
GRANT role1 TO role2;
For more information, see Database role hierarchies and inheritance.
Grant access to database roles to IAM principals
Before a principal can use a database role to access Spanner resources, you must grant them access to the database role.
Console
To grant access to database roles to an IAM principal, follow these steps:
On the database Overview page, click SHOW INFO PANEL if the Info panel is not already open.
Click ADD PRINCIPAL.
On the Grant access to database_name panel, under Add principals, specify one or more IAM principals.
Under Assign roles, in the Select a role menu, select Cloud Spanner > Cloud Spanner Fine-grained Access User.
You need to grant this role only once to each principal. It makes the principal a fine-grained access control user.
Click ADD ANOTHER ROLE.
In the Select a role menu, select Cloud Spanner > Cloud Spanner Database Role User.
Follow these steps to create the IAM condition that specifies the roles to grant.
Next to the Cloud Spanner Database Role User role, click ADD IAM CONDITION.
In the Add condition panel, enter a title and optional description for the condition.
If you're granting a single database role, you would typically include the role name in the condition title. If you're granting multiple roles, you could indicate something about the set of roles.
Click CONDITION EDITOR.
In the Expression field, enter the following code:
resource.type == "spanner.googleapis.com/DatabaseRole" && resource.name.endsWith("/ROLE")
Replace
ROLE
with your role name.Or, to grant access to the principal to more than one role, add more conditions with the or (
||
) operator, as shown in the following example:resource.type == "spanner.googleapis.com/DatabaseRole" && (resource.name.endsWith("/ROLE1") || resource.name.endsWith("/ROLE2"))
This code grants two roles. Replace
ROLE1
andROLE2
with your role names. To grant more than two roles, add more or conditions.You can use any condition expression that is supported by IAM. For more information, see Overview of IAM conditions.
Click Save.
Back in the previous panel, verify that the condition appears under the IAM Condition column next to the Role field.
Click Save.
Back on the Info panel, under Role/Principal, notice that Cloud Spanner Database Role User appears for each defined condition.
The number in parentheses next to the condition indicates the number of principals who are granted the database role by that condition. You can click the expander arrow to view the list of principals.
To correct errors in database role names or conditions, or to add additional database roles for a principal, follow these steps:
Expand the Cloud Spanner Database Role User entry that lists the condition that you want.
Click the Edit (pencil) icon next to a principal.
On the Edit access to database_name panel, do one of the following:
Click ADD ANOTHER ROLE.
To edit the condition, click the Edit (pencil) icon adjacent to the condition name. Then on the Edit condition page, click CONDITION EDITOR, make corrections, and click Save twice.
gcloud
To grant access to database roles to an IAM principal, follow these steps:
Enable fine-grained access control for the principal by using the
gcloud spanner databases add-iam-policy-binding
command as follows:gcloud spanner databases add-iam-policy-binding DATABASE_NAME \ --instance=INSTANCE_NAME \ --role=roles/spanner.fineGrainedAccessUser \ --member=MEMBER_NAME \ --condition=None
MEMBER_NAME
is the identifier for the principal. It must be of the formuser|group|serviceAccount:email
ordomain:domain
.This command makes the principal a fine-grained access control user. Submit this command only once for each principal.
If successful, the command outputs the entire policy for the database.
Grant permission to use one or more database roles by using the
gcloud spanner databases add-iam-policy-binding
command as follows:gcloud spanner databases add-iam-policy-binding DATABASE_NAME \ --instance=INSTANCE_NAME \ --role=roles/spanner.databaseRoleUser \ --member=MEMBER_NAME \ --condition=CONDITION
MEMBER_NAME
is the identifier for the principal. It must be of the formuser|group|serviceAccount:email
ordomain:domain
.CONDITION
is an IAM condition expression that specifies the roles to grant to the principal.CONDITION
has the following form:--condition='expression=(resource.type == "spanner.googleapis.com/DatabaseRole" && resource.name.endsWith("/ROLE1")),title=TITLE,description=DESCRIPTION'
Or, to grant access to the principal to more than one role, add more conditions with the or (
||
) operator, as shown in the following example:--condition='expression=(resource.type == "spanner.googleapis.com/DatabaseRole" && (resource.name.endsWith("/ROLE1") || resource.name.endsWith("/ROLE2"))),title=TITLE,description=DESCRIPTION'
This code grants two roles. Replace
ROLE1
andROLE2
with your role names. To grant more than two roles, add more or conditions with the||
operator.You can use any condition expression that is supported by IAM. For more information, see Overview of IAM conditions.
If successful, the command outputs the entire policy for the database.
The following example grants the database roles
hr_rep
andhr_manager
to the principaljsmith@example.com
.gcloud spanner databases add-iam-policy-binding myDatabase \ --instance=myInstance \ --role=roles/spanner.databaseRoleUser \ --member=user:jsmith@example.com \ --condition='expression=(resource.type == "spanner.googleapis.com/DatabaseRole" && (resource.name.endsWith("/hr_rep") || resource.name.endsWith("/hr_manager"))),title=HR roles,description=Grant permissions on HR roles'
Client libraries
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Inform users and developers to start using database roles
After initial fine-grained access control configuration is complete, inform users and application developers that they must begin using database roles.
Fine-grained access control users must begin specifying a database role when they access Spanner databases through the Google Cloud console or the Google Cloud CLI.
Applications that use fine-grained access control must specify a database role when accessing the database.
For more information, see Access a database with fine-grained access control.
Transition a principal to fine-grained access control
To transition an IAM principal from database-level access control to fine-grained access control, follow these steps:
Enable fine-grained access control for the principal and grant access to all required database roles, as described in Grant access to database roles to IAM principals.
Update all applications that run as this principal. Specify the appropriate database roles in calls to client library methods.
Revoke all IAM database-level roles from the principal. This way, access for the principal is governed by only one method.
Exception: To interact with Spanner resources in the Google Cloud console, all users must have the
roles/spanner.viewer
IAM role.To revoke IAM database-level roles, follow the instructions in Remove database-level permissions.
List database roles
You can list the database roles associated with a database.
Console
To list database roles, enter the following query on the Spanner Studio page for the database:
GoogleSQL
SELECT * FROM INFORMATION_SCHEMA.ROLES;
PostgreSQL
SELECT * FROM information_schema.enabled_roles;
The response includes the current role and roles whose privileges the current role can use through inheritance. To fetch all roles, use the Google Cloud CLI command.
gcloud
To obtain an unfiltered list of database roles, enter the following command.
It requires the spanner.databaseRoles.list
permission.
gcloud spanner databases roles list --database=DATABASE_NAME --instance=INSTANCE_NAME
Client libraries
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
View the privileges granted to a database role
To view the privileges granted to a role, run the following queries:
GoogleSQL
SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES WHERE grantee = 'ROLE_NAME'; SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES WHERE grantee = 'ROLE_NAME'; SELECT * FROM INFORMATION_SCHEMA.CHANGE_STREAM_PRIVILEGES WHERE grantee = 'ROLE_NAME';
INFORMATION_SCHEMA.TABLE_PRIVILEGES
returns privileges on both tables and views.
The SELECT
, INSERT
, and UPDATE
privileges in TABLE_PRIVILEGES
are also
shown in COLUMN_PRIVILEGES
.
PostgreSQL
SELECT * FROM information_schema.table_privileges WHERE grantee = 'ROLE_NAME'; SELECT * FROM information_schema.column_privileges WHERE grantee = 'ROLE_NAME'; SELECT * FROM information_schema.change_stream_privileges WHERE grantee = 'ROLE_NAME';
information_schema.table_privileges
returns privileges on both tables and views.
The SELECT
, INSERT
, and UPDATE
privileges in table_privileges
are also
shown in column_privileges
.
View fine-grained access control users
To view a list of principals that are fine-grained access control users, run the following
command. To run the command, you must have the Cloud Asset API enabled on your
project, and you must have the
cloudasset.assets.searchAllIamPolicies
IAM permission.
gcloud asset search-all-iam-policies \ --scope=projects/PROJECT_NAME \ --query='roles=roles/spanner.fineGrainedAccessUser AND resource=//spanner.googleapis.com/projects/PROJECT_NAME/instances/INSTANCE_NAME/databases/DATABASE_NAME' \ --flatten=policy.bindings[].members[] \ --format='table(policy.bindings.members)'
Output is similar to the following:
MEMBERS user:222larabrown@gmail.com user:baklavainthebalkans@gmail.com serviceAccount:cs-fgac-sa-1@cloud-spanner-demo.google.com.iam.gserviceaccount.com serviceAccount:cs-fgac-sa-2@cloud-spanner-demo.google.com.iam.gserviceaccount.com
For more information, see Enabling an API in your Google Cloud project.
View IAM principals with access to a database role
To view a list of principals who have been granted access to a particular
database role, run the following command. To run the command, you must have the
Cloud Asset API enabled on your project, and you must have the
cloudasset.assets.searchAllIamPolicies
IAM permission.
gcloud asset search-all-iam-policies \ --scope=projects/PROJECT_NAME \ --query='roles=roles/spanner.databaseRoleUser AND policy:"resource.name" AND policy:/ROLE_NAME AND resource=//spanner.googleapis.com/projects/PROJECT_NAME/instances/INSTANCE_NAME/databases/DATABASE_NAME' \ --flatten=policy.bindings[].members[] \ --format='table(policy.bindings.members)'
Output is similar to the following:
MEMBERS 222larabrown@gmail.com
View the IAM conditions for a principal
To view a list of IAM conditions that were specified when granting the role Cloud Spanner Database Role User to a principal, run the following command:
gcloud asset search-all-iam-policies \ --scope=projects/PROJECT_NAME \ --query='roles=roles/spanner.databaseRoleUser AND policy:resource.name AND policy:"PRINCIPAL_IDENTIFIER" AND resource=//spanner.googleapis.com/projects/PROJECT_NAME/instances/INSTANCE_NAME/databases/DATABASE_NAME' \ --flatten=policy.bindings[] \ --format='table(policy.bindings.condition.expression)'
where PRINCIPAL_IDENTIFIER is:
{ user:user-account-name | serviceAccount:service-account-name }
PRINCIPAL_IDENTIFIER examples:
user:222larabrown@gmail.com serviceAccount:cs-fgac-sa-1@cloud-spanner-demo.google.com.iam.gserviceaccount.com
The following sample output shows two condition expressions.
EXPRESSION resource.type == "spanner.googleapis.com/DatabaseRole" && resource.name.endsWith("/hr_analyst") resource.type == "spanner.googleapis.com/DatabaseRole" && resource.name.endsWith("/hr_manager")
Check IAM policies for missing database role conditions
After you have granted access to database roles to principals, we recommend that you ensure that each IAM binding has a condition specified.
To perform this check, run the following command:
gcloud asset search-all-iam-policies \ --scope=projects/PROJECT_NAME \ --query='roles:roles/spanner.databaseRoleUser AND resource=//spanner.googleapis.com/projects/PROJECT_NAME/instances/INSTANCE_NAME/databases/DATABASE_NAME' --flatten=policy.bindings[].members[]
The output is similar to the following:
ROLE MEMBERS EXPRESSION roles/spanner.databaseRoleUser serviceAccount:cs-fgac-sa-1@... roles/spanner.databaseRoleUser serviceAccount:cs-fgac-sa-2@... resource.type == "spanner…"
Note that the first result is missing a condition and therefore the principals in this binding have access to all database roles.
Drop a database role
Dropping a database role automatically revokes the membership of other roles from the role, and revokes the role's membership in other roles.
To drop a database role, you must first do the following:
- Revoke all fine-grained access control privileges from the role.
- Remove any IAM policy bindings that refer to that role, so that a database role created later with the same name does not inherit those bindings.
Console
To drop a database role, follow these steps:
On the database Overview page, click Spanner Studio.
To revoke privileges from the role, enter a
REVOKE
statement.GoogleSQL
For syntax details for the
REVOKE
statement, see GoogleSQL data definition language. For information about privileges, see Fine-grained access control privileges.For example, to revoke
SELECT
,INSERT
, andUPDATE
on tablesemployees
andcontractors
from the database rolehr_manager
, enter the following statement:REVOKE SELECT, INSERT, UPDATE ON TABLE employees, contractors FROM ROLE hr_manager;
PostgreSQL
For syntax details for the
REVOKE
statement, see PostgreSQL data definition language. For information about privileges, see Fine-grained access control privileges.For example, to revoke the
SELECT
,INSERT
, andUPDATE
privileges on theemployees
andcontractors
tables from the database rolehr_manager
, enter the following statement:REVOKE SELECT, INSERT, UPDATE ON TABLE employees, contractors FROM hr_manager;
You can use a DDL template for the
REVOKE
statement. In the Explorer pane, navigate to the role for which you want to revoke privilege. Click View actions and select the type of privilege you want to revoke access for this role. TheREVOKE
template statement populates in a new editor tab.Delete any IAM condition associated with the role.
In the list of roles on the Info panel, locate the Cloud Spanner Database Role User role that has the condition title of interest adjacent to it, and then expand the role to view the principals that have access to the role.
For one of the principals, click the Edit principal (pencil) icon.
On the Edit access page, click the Delete role (trash can) icon adjacent to the Cloud Spanner Database Role User role.
Click Save.
Repeat the previous three steps for other principals who are listed under the condition.
To drop the role, go to the Spanner Studio page and enter the following statement:
DROP ROLE ROLE_NAME;
Click Submit.
gcloud
To revoke all privileges for a role and then drop the role, use the
gcloud spanner databases ddl update
command as follows:GoogleSQL
gcloud spanner databases ddl update DATABASE_NAME \ --instance=INSTANCE_NAME \ --ddl='REVOKE PERMISSIONS ON TABLE TABLE_NAME FROM ROLE ROLE_NAME; DROP ROLE ROLE_NAME;'
PostgreSQL
gcloud spanner databases ddl update DATABASE_NAME \ --instance=INSTANCE_NAME \ --ddl='REVOKE PERMISSIONS ON TABLE TABLE_NAME FROM ROLE_NAME; DROP ROLE ROLE_NAME;'
Valid values for
PERMISSIONS
areSELECT
,INSERT
,UPDATE
, andDELETE
.To delete any related IAM conditions, use the
gcloud spanner databases remove-iam-policy-binding
command as follows:gcloud spanner databases remove-iam-policy-binding DATABASE_NAME \ --instance=INSTANCE_NAME \ --role=ROLE_NAME \ --member=MEMBER_NAME \ --condition=CONDITION
MEMBER_NAME
is the identifier for the principal. It must be of the formuser|group|serviceAccount:email
ordomain:domain
.CONDITION
is an IAM condition expression that specifies the roles to grant to the principal.CONDITION
has the following form:--condition='expression=(resource.type == "spanner.googleapis.com/DatabaseRole" && (resource.name.endsWith("/ROLE1") || resource.name.endsWith("/ROLE2"))),title=TITLE,description=DESCRIPTION'
The entire condition specification must exactly match the condition specification that was used in the command that granted permission, including title and description.
Client libraries
These code samples both create and drop a database role.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
More information
- About fine-grained access control
- Fine-grained access control for change streams
- Fine-grained access control privileges
- GoogleSQL DDL reference
- Make schema updates