Estratégias de privacidade de dados

A privacidade de dados evita que pessoas não autorizadas tenham acesso a dados como informações de identificação pessoal (PII). Nesta página, descrevemos várias abordagens de privacidade de dados que podem ser usadas para proteger suas PII no Cloud SQL.

É possível usar o Cloud SQL para armazenar com segurança suas PIIs. Essas informações precisam ser processadas com a maior proteção de privacidade possível, para que não sejam acessadas por acidente. Por exemplo, se você armazenar informações de cartão de crédito ou dados de saúde nos seus bancos de dados, poderá usar o Cloud SQL para ocultar ou mascarar essas PIIs de usuários sem privilégios.

Adote as seguintes estratégias para proteger suas PII no Cloud SQL:

Segurança no nível da coluna

A segurança no nível da coluna permite restringir quem pode acessar o conteúdo de colunas específicas em tabelas de banco de dados. Os privilégios no nível da coluna são aplicáveis às instruções INSERT, UPDATE, SELECT e REFERENCES.

Por exemplo, suponha que você quer gerenciar as PIIs de dois usuários em um site de varejo: Jack e Alice.

--User: "admin"

CREATE SCHEMA secure_schema;

CREATE TABLE secure_schema.user_details(id bigint, name text, age smallint, email_id text, password text);

--For this example, passwords are stored in plain text for demonstration
--purposes only. In production, never store passwords in plain text.

INSERT INTO secure_schema.user_details VALUES(1,'jack',34,'jack@example.com','testpass');
INSERT INTO secure_schema.user_details VALUES(2,'alice',37,'alice@example.com','testpass');

GRANT USAGE ON SCHEMA secure_schema TO analyst_ro;

--Grant read permissions on specific columns only.

GRANT SELECT (id, name, age) ON secure_schema.user_details TO analyst_ro;

--User: "analyst_ro"

SELECT * FROM secure_schema.user_details;
ERROR:  permission denied for table user_details

SELECT name, age, password FROM secure_schema.user_details;
ERROR:  permission denied for table user_details

SELECT id, name,age FROM secure_schema.user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

Se você incluir as colunas restritas na instrução SELECT ou digitar SELECT *, uma mensagem de erro vai aparecer. O Cloud SQL protege as PIIs de Jack e Alice nessas colunas.

Também é possível usar uma única instrução GRANT para combinar privilégios diferentes.

GRANT SELECT (id,name,age), UPDATE (name) ON secure_schema.user_details TO analyst_ro;

Abordagem baseada em visualização

Você também pode ter segurança no nível da coluna criando uma visualização com base em uma tabela, excluindo ou mascarando colunas que você quer ocultar de outros usuários e fornecendo acesso a essa visualização em vez de à tabela.

O seguinte exemplo mostra como usar uma abordagem baseada em visualização no site de varejo para proteger as PIIs de Jack e Alice:

--User: "admin"

CREATE SCHEMA analyst_ro;
CREATE VIEW analyst_ro.user_details AS SELECT id, name, age FROM secure_schema.user_details;
GRANT USAGE ON SCHEMA analyst_ro TO analyst_ro;
GRANT SELECT ON analyst_ro.user_details TO analyst_ro;

--User: "analyst_ro"

SELECT id,name,age FROM user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

SELECT * FROM user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

Neste exemplo, um esquema separado é criado para que a visualização mantenha o mesmo nome da tabela. Com a abordagem baseada em visualização, é possível usar SELECT *.

Também é possível criar uma visualização e mascarar as colunas da tabela do banco de dados para que usuários sem privilégios não possam consultar as PIIs mascaradas.

CREATE VIEW analyst_ro.user_details AS SELECT id, name, age, 'redacted@example.com' as email_id,'*****'::text as password FROM secure_schema.user_details;

SELECT * FROM user_details;
 id | name  | age |     email_id         | password
----+-------+-----+----------------------+---------
  1 | jack  |  34 | redacted@example.com | *****
  2 | alice |  37 | redacted@example.com | *****

Segurança no nível da linha

A segurança no nível da coluna e uma abordagem baseada em visualização permitem ocultar de usuários específicos as PIIs em colunas de tabelas de banco de dados. No entanto, você também pode querer filtrar esses dados e conceder acesso a linhas específicas de uma tabela. Essa tabela contém PIIs que só podem ser acessadas por alguns usuários, com base nas condições de usuários qualificados. Isso é conhecido como segurança no nível da linha.

A segurança no nível da linha é útil para aplicativos multilocatários em que os usuários só têm privilégios de acesso/leitura e acesso/gravação com relação às próprias PIIs. No Cloud SQL, as tabelas podem ter políticas de segurança em nível de linha que limitam as linhas que cada usuário pode consultar, por meio da criação de consultas, ou as linhas que eles podem inserir, atualizar ou excluir, por meio da execução de comandos de modificação de dados.

No exemplo do site de varejo, é possível implementar a segurança no nível da linha para Jack e Alice a fim de que eles possam visualizar as próprias PIIs, mas não modificá-las ou excluí-las.

--User: "admin"
--Create and enable a policy for row-level security

CREATE POLICY user_details_rls_pol ON secure_schema.user_details FOR ALL TO PUBLIC USING (name=current_user);
ALTER TABLE secure_schema.user_details ENABLE ROW LEVEL SECURITY;

SELECT * FROM secure_schema.user_details;
 id | name  | age |     email_id      | password
----+-------+-----+-------------------+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--User: "jack"

SELECT * FROM secure_schema.user_details;
 id | name | age |    email_id      | password
----+------+-----+------------------+---------
  1 | jack |  34 | jack@example.com | testpass

--User: "alice"

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+-------------------+---------
  2 | alice |  37 | alice@example.com | testpass

Os usuários atribuídos a papéis com o atributo BYPASSRLS podem ignorar a segurança no nível da linha ao acessar uma tabela. Os proprietários de tabelas também podem ignorar a segurança no nível da linha. Se você quiser submeter um proprietário de tabela à segurança no nível da linha, use o comando ALTER TABLE ... FORCE ROW LEVEL SECURITY.

Às vezes, você não quer aplicar esse tipo de segurança às linhas de uma tabela de banco de dados. Por exemplo, se você usar pg_dump para fazer um backup da tabela, nenhuma linha deve ser omitida do backup. Para evitar que isso ocorra, defina o parâmetro de configuração row_security como OFF ao fazer o backup. Se alguma linha for filtrada com base na segurança no nível da linha, uma mensagem de erro vai aparecer.

Mascarar e anonimizar os dados

Além de mascarar os dados seguindo uma abordagem baseada em visualização, é possível mascará-los usando a extensão postgresql_anonymizer. Essa extensão mascara ou substitui PIIs ou dados comercialmente confidenciais de um banco de dados PostgreSQL.

Ao usar a extensão em vez de uma abordagem baseada em visualização, você tem os seguintes benefícios:

  • Há várias funções de mascaramento, como substituição, randomização, simulação, pseudonimização, embaralhamento parcial, embaralhamento, adição de ruído e generalização.

  • É possível gerar dados mascarados significativos que podem ser usados para testes funcionais e processamento de dados.

  • Use a linguagem de definição de dados (DDL) do PostgreSQL para declarar regras de mascaramento e especificar a estratégia de anonimização na definição da tabela.

Instalar e configurar a extensão postgresql_anonymizer

Para usar essa extensão em uma instância do Cloud SQL, siga estas etapas:

  1. Edite a instância e defina cloudsql.enable_anon flag como on. Para informações sobre como configurar flags e analisar aquelas que têm suporte nessa extensão, consulte Configurar flags de banco de dados.

  2. Execute o seguinte comando para criar a extensão no banco de dados:

    --Connect to the PostgreSQL database
    
    CREATE EXTENSION IF NOT EXISTS anon CASCADE;
    SELECT anon.init();
    

Depois de instalar e configurar a extensão, use-a na instância para implementar estratégias de anonimização de máscara dinâmica, máscara estática e dump anônimo.

Máscara dinâmica

Use máscaras dinâmicas a fim de definir regras de mascaramento para usuários específicos. Esses usuários não têm acesso às PIIs. Em vez disso, são exibidos dados mascarados. Todos os outros usuários têm acesso aos dados não mascarados. Isso é útil em ambientes de produção quando você não quer alterar as PIIs, mas apenas ocultá-las de determinados usuários.

No exemplo do site de varejo, é possível implementar máscaras dinâmicas para que o administrador possa visualizar os endereços de e-mail e as senhas não mascarados de Jack e Alice, mas apenas dados mascarados sejam exibidos ao analista.

--Activate the dynamic masking engine

SELECT anon.start_dynamic_masking();

--Declare the masking user and masking rules
--analyst_ro is the masked user with select privileges on the
--user_details table

SECURITY LABEL FOR anon ON ROLE analyst_ro IS 'MASKED';

SECURITY LABEL FOR anon ON COLUMN secure_schema.user_details.email_id IS 'MASKED WITH FUNCTION anon.fake_email()';
SECURITY LABEL FOR anon ON COLUMN secure_schema.user_details.password  IS 'MASKED WITH FUNCTION anon.hash(password)';

--User: "admin" (can see all unmasked data)

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+------------  -----+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--User:"analyst_ro" (note that the "email_id" and "password" columns are
--replaced with masked data,)
--Data in the password column is truncated for better formatting.

SELECT * FROM secure_schema.user_details;
 id | name  | age |       email_id         | password
----+-------+-----+-----------------  -----+----------------
  1 | jack  |  34 | alisontodd@example.com | 13d249f2cb4127b
  2 | alice |  37 | amanda35@example.com   | 13d249f2cb4127b

Máscara estática

Use máscaras estáticas para remover as PIIs de uma tabela, de acordo com os critérios definidos nas regras de mascaramento, e substituir essas informações por dados mascarados. Os usuários não conseguem recuperar os dados não mascarados. Isso é útil em ambientes de teste, quando você quer alterar as PIIs e não quer que os usuários visualizem essas informações.

No exemplo do site de varejo, é possível implementar máscaras estáticas para que nenhum usuário possa consultar os endereços de e-mail e as senhas não mascarados de Jack e Alice. Em vez disso, apenas dados mascarados são exibidos.

--User: "admin"

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+--------------  ---+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--Apply earlier defined masking rules to the table permanently.
--Now all users see masked data only.

SELECT anon.anonymize_table('secure_schema.user_details');
 anonymize_table
-----------------
 t

--User: "analyst_ro"
--Data in the password column is truncated for better formatting.

select * from secure_schema.user_details;
 id | name  | age |           email_id              |  password
----+-------+-----+-------------------------  ------+---------------
  1 | jack  |  34 | christophercampbell@example.com | 13d249f2cb412c
  2 | alice |  37 | annebenitez@example.com         | 13d249f2cb4127

Dump anônimo

Use dumps anônimos a fim de exportar dados mascarados para um arquivo SQL. No exemplo do site de varejo, é possível criar um arquivo dump para os dados mascarados contidos na tabela user_details.

--Launch pg_dump_anon with the masked user to apply earlier defined --masking rules

pg_dump_anon -h HOSTIP -p 5432 -d DATABASE_NAME -U analyst_ro --table=secure_schema.user_details --file=user_details_anonysms.sql

Criptografar dados

Embora seja possível mascarar PIIs, as informações são armazenadas no banco de dados como texto simples. Um administrador pode acessar essas informações.

Use a extensão pgcrypto para criptografar as PIIs antes de armazená-las. Dessa forma, apenas os usuários com uma chave de criptografia válida podem descriptografar as informações e exibi-las como texto simples.

A extensão pgcrypto tem várias funções de hash e criptografia.

Hash

Um hash é uma função criptográfica unidirecional em que você só precisa criptografar as PIIs. Isso é útil para armazenar senhas em um formato de hash e fazer a correspondência entre as senhas inseridas pelo usuário e aquelas com hash. As senhas com hash nunca são descriptografadas em texto simples.

No exemplo do site de varejo, você pode usar a extensão pgcrypto para gerar hash da senha de Jack antes de armazená-la na tabela user_details.

--Hash passwords before storing them in the user_details table.

TRUNCATE TABLE secure_schema.user_details;
INSERT INTO secure_schema.user_details VALUES(1,'jack',34,'jack@example.com',crypt('testpassword', gen_salt('bf')));

--Match the hashed data with user entered password

SELECT id, name FROM secure_schema.user_details WHERE email_id = 'jack@example.com' AND password = crypt('testpassword', password);
 id | name
----+-----
  1 | jack

Criptografar

Use uma função criptográfica de criptografia para criptografar as PIIs com uma chave. Os usuários precisam dessa chave para descriptografar as informações em texto simples. Isso é útil para armazenar informações de cartão de crédito e detalhes bancários quando os aplicativos precisam recuperar as PIIs em um formato legível.

No exemplo do site de varejo, a senha e o endereço de e-mail de Jack são criptografados. Os usuários que têm a chave de criptografia podem descriptografar essas informações e exibi-las como texto simples. Todos os outros usuários recebem uma mensagem de erro.

--"user_acc_key" is the encryption key

TRUNCATE TABLE secure_schema.user_details;
INSERT INTO secure_schema.user_details VALUES(1,'jack',34,pgp_sym_encrypt('jack@example.com','user_acc_key'),pgp_sym_encrypt('testpassword','user_acc_key'));

--User: "admin" (queries without an encryption key)
--Data in the email_id and password columns are truncated for better
--formatting.

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id     | password
----+-------+-----+-----------------+-------------------
  1 | jack |  34 | \xc30d0407030209 | \xc30d040703028962

--User: "app_user" (queries with a valid encryption key)

SELECT name,pgp_sym_decrypt(email_id::bytea,'user_acc_key'),pgp_sym_decrypt(password::bytea,'user_acc_key') FROM secure_schema.user_details;
 name | pgp_sym_decrypt   | pgp_sym_decrypt
------+-------------------+----------------
 jack | jack@example.com  | testpassword

--If a user uses the wrong encryption key, then the following error message appears:

SELECT name,pgp_sym_decrypt(email_id::bytea,'user_bad_key'),
pgp_sym_decrypt(password::bytea,'user_bad_key') FROM secure_schema.user_details;
ERROR:  Wrong key or corrupt data

A seguir

Saiba mais sobre os seguintes controles adicionais que podem ser usados para proteger PIIs contra acesso não autorizado: