Aceda a uma base de dados com controlo de acesso detalhado

Esta página explica como aceder a uma base de dados do Spanner quando é um utilizador do controlo de acesso detalhado.

Para saber mais sobre o controlo de acesso detalhado, consulte o artigo Acerca do controlo de acesso detalhado.

Enquanto utilizador do controlo de acesso detalhado, tem de selecionar uma função de base de dados para usar na execução de consultas e declarações SQL, e para realizar operações de linhas numa base de dados. A seleção de funções persiste durante toda a sessão até alterar a função.

Quando envia uma consulta, uma DML ou uma operação de linhas, o Spanner verifica a autorização através das seguintes regras:

Google Cloud consola

O Spanner verifica primeiro se tem autorizações do IAM ao nível da base de dados. Se for esse o caso, a Google Cloud consola não mostra um seletor de funções da base de dados e a sua sessão prossegue com as suas autorizações ao nível da base de dados.

  • Se tiver apenas privilégios de controlo de acesso detalhado e nenhuma autorização ao nível da base de dados de IAM, tem de lhe ter sido concedido acesso à função do sistema spanner_sys_reader ou a uma das respetivas funções de membro. Selecione uma função na página Vista geral da base de dados para que a sessão da Google Cloud consola prossiga com os privilégios necessários.

SDK Google Cloud

Se especificar uma função de base de dados quando envia uma consulta, DML ou uma operação de linha, o Spanner verifica os privilégios de controlo de acesso detalhado. Se a verificação falhar, o Spanner não verifica as autorizações do IAM ao nível da base de dados e a operação falha.

Se não especificar uma função da base de dados, o Spanner verifica as autorizações de IAM ao nível da base de dados e, se as verificações forem bem-sucedidas, a sessão prossegue com as autorizações ao nível da base de dados.

Use estes métodos para especificar uma função da base de dados quando acede a uma base de dados do Spanner:

Consola

  1. Selecione uma base de dados e, de seguida, na página Vista geral da base de dados, clique no ícone Alterar função da base de dados (lápis) junto ao campo Função atual.

    Por predefinição, quando um utilizador do controlo de acesso detalhado inicia sessão, este campo tem o valor public. Para informações sobre a função do sistema public, consulte o artigo Funções do sistema de controlo de acesso detalhado.

  2. Na caixa de diálogo Alterar função da base de dados, selecione outra função na lista de funções disponíveis.

  3. Clique em Atualizar.

    O campo Função atual mostra a nova função.

gcloud

  • Adicione a opção --database-role ao comando gcloud spanner databases execute-sql da seguinte forma:

    gcloud spanner databases execute-sql DATABASE_NAME \
    --instance=INSTANCE_NAME \
    --sql="SELECT * from TABLE_NAME;" \
    --database-role=ROLE_NAME

Bibliotecas cliente

C++

void ReadDataWithDatabaseRole(std::string const& project_id,
                              std::string const& instance_id,
                              std::string const& database_id,
                              std::string const& role) {
  namespace spanner = ::google::cloud::spanner;
  auto client = spanner::Client(spanner::MakeConnection(
      spanner::Database(project_id, instance_id, database_id),
      google::cloud::Options{}.set<spanner::SessionCreatorRoleOption>(role)));
  spanner::SqlStatement select_star("SELECT * FROM Singers");
  auto rows = client.ExecuteQuery(std::move(select_star));
  using RowType =
      std::tuple<std::int64_t, std::string, std::string, spanner::Bytes>;
  for (auto& row : spanner::StreamOf<RowType>(rows)) {
    if (!row) throw std::move(row).status();
    std::cout << "SingerId: " << std::get<0>(*row) << ", "
              << "FirstName: " << std::get<1>(*row) << ", "
              << "LastName: " << std::get<2>(*row) << "\n";
  }
}

C#


using Google.Cloud.Spanner.Data;
using System.Collections.Generic;
using System.Threading.Tasks;

public class ReadDataWithDatabaseRoleAsyncSample
{
    public class Singer
    {
        public int SingerId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public async Task<List<Singer>> ReadDataWithDatabaseRoleAsync(string projectId, string instanceId, string databaseId, string databaseRole)
    {
        string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
        string tableName = "Singers";

        var spannerConnectionStringBuilder = new SpannerConnectionStringBuilder
        {
            ConnectionString = connectionString,
            DatabaseRole = databaseRole
        };
        using var connection = new SpannerConnection(spannerConnectionStringBuilder);
        var createSelectCmd = connection.CreateSelectCommand($"SELECT * FROM {tableName}");
        using var reader = await createSelectCmd.ExecuteReaderAsync();
        var singers = new List<Singer>();
        while (await reader.ReadAsync())
        {
            singers.Add(new Singer
            {
                SingerId = reader.GetFieldValue<int>("SingerId"),
                FirstName = reader.GetFieldValue<string>("FirstName"),
                LastName = reader.GetFieldValue<string>("LastName"),
            });
        }
        return singers;
    }
}

Ir


import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"
)

func readDataWithDatabaseRole(w io.Writer, db string, databaseRole string) error {
	// databaseRole = "parent"
	ctx := context.Background()
	cfg := spanner.ClientConfig{
		DatabaseRole: databaseRole,
	}
	client, err := spanner.NewClientWithConfig(ctx, db, cfg)
	if err != nil {
		return err
	}
	defer client.Close()

	// Read all albums.
	iter := client.Single().Read(ctx, "Albums", spanner.AllKeys(),
		[]string{"SingerId", "AlbumId", "AlbumTitle"})
	defer iter.Stop()
	for {
		row, err := iter.Next()
		if err == iterator.Done {
			return nil
		}
		if err != nil {
			return err
		}
		var singerID, albumID int64
		var albumTitle string
		if err := row.Columns(&singerID, &albumID, &albumTitle); err != nil {
			return err
		}
		fmt.Fprintf(w, "%d %d %s\n", singerID, albumID, albumTitle)
	}
}

Java

import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.KeySet;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerOptions;
import java.util.Arrays;

public class ReadDataWithDatabaseRole {

  static void readDataWithDatabaseRole() {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    String role = "my-role";
    readDataWithDatabaseRole(projectId, instanceId, databaseId, role);
  }

  static void readDataWithDatabaseRole(
      String projectId, String instanceId, String databaseId, String role) {
    try