Stratégies de confidentialité des données

La confidentialité des données protège les données telles que les informations permettant d'identifier personnellement l'utilisateur des personnes qui ne devraient pas y avoir accès. Cette page décrit plusieurs approches de la confidentialité des données que vous pouvez utiliser pour protéger vos informations permettant d'identifier personnellement l'utilisateur dans Cloud SQL.

Vous pouvez utiliser Cloud SQL pour stocker vos informations personnelles de manière sécurisée. Vous voulez vous assurer que ces informations sont traitées avec la protection de la confidentialité la plus élevée afin qu'elles ne soient pas accessibles par inadvertance. Par exemple, si vous stockez des informations de carte de crédit ou des données de santé dans vos bases de données, vous pouvez utiliser Cloud SQL pour masquer les informations permettant d'identifier personnellement les utilisateurs non privilégiés.

Utilisez les stratégies suivantes pour sécuriser vos informations permettant d'identifier l'utilisateur dans Cloud SQL :

Sécurité au niveau des colonnes

La sécurité au niveau des colonnes vous permet de limiter les utilisateurs autorisés à voir le contenu dans des colonnes spécifiques de tables de base de données. Les droits au niveau des colonnes s'appliquent aux instructions INSERT, UPDATE, SELECT et REFERENCES.

Prenons l'exemple d'un site Web de vente au détail sur lequel vous souhaitez gérer les informations personnelles de deux utilisateurs, Jackson et 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

Si vous incluez les colonnes restreintes dans l'instruction SELECT ou si vous saisissez SELECT *, un message d'erreur s'affiche. Cloud SQL sécurise les informations permettant d'identifier l'utilisateur pour Jack et Alice dans ces colonnes.

Vous pouvez également utiliser une seule instruction GRANT pour combiner différents droits.

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

Approche basée sur les vues

Vous pouvez également assurer la sécurité au niveau des colonnes en créant une vue sur une table, en excluant ou en masquant les colonnes que vous souhaitez rendre invisible aux autres utilisateurs, et en fournissant l'accès à la vue plutôt qu'à la table.

L'exemple suivant montre comment utiliser une approche basée sur les vues pour le site Web de vente au détail afin de sécuriser les informations permettant d'identifier l'utilisateur pour Jack et 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

Dans cet exemple, un schéma distinct est créé pour que la vue garde le même nom que la table. Avec l'approche basée sur les vues, vous pouvez utiliser SELECT *.

Vous pouvez également créer une vue et masquer les colonnes de la table de base de données afin que les utilisateurs non privilégiés ne puissent pas voir les informations permettant d'identifier l'utilisateur qui sont masquées.

CREATE OR REPLACE 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 | *****

Sécurité au niveau des lignes

La sécurité au niveau des colonnes et l'approche basée sur les vues vous permettent de masquer des informations permettant d'identifier personnellement l'utilisateur dans les colonnes de tables de base de données pour des utilisateurs spécifiques. Cependant, vous pouvez parfois avoir besoin de filtrer ces données et d'accorder l'accès à des lignes spécifiques d'une table. Ce tableau contient les informations permettant d'identifier personnellement les utilisateurs auxquelles seuls certains utilisateurs ont accès, en fonction des conditions éligibles. C'est ce qu'on appelle la sécurité au niveau des lignes.

La sécurité au niveau des lignes est utile pour les applications mutualisées dans lesquelles les utilisateurs disposent de droits d'accès en lecture et en écriture uniquement à leurs propres informations permettant de les identifier personnellement. Dans Cloud SQL, les tables peuvent comporter des règles de sécurité au niveau des lignes qui limitent, par utilisateur, les lignes que les utilisateurs peuvent afficher en créant des requêtes, ou les lignes que les utilisateurs peuvent insérer, mettre à jour ou supprimer en exécutant des commandes de modification de données.

Pour l'exemple du site Web de commerce de détail, vous pouvez mettre en œuvre la sécurité au niveau des lignes pour Jackson et Alice afin que chaque utilisateur puisse accéder uniquement à ses propres informations permettant d'identifier l'utilisateur.

--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

Les utilisateurs affectés à des rôles avec l'attribut BYPASSRLS peuvent contourner la sécurité au niveau des lignes lorsqu'ils accèdent à une table. Les propriétaires de table peuvent également contourner la sécurité au niveau des lignes. Si vous souhaitez soumettre un propriétaire de table à une sécurité au niveau des lignes, utilisez la commande ALTER TABLE ... FORCE ROW LEVEL SECURITY.

Il peut arriver que vous ne souhaitiez pas appliquer une sécurité au niveau des lignes aux lignes d'une table de base de données. Par exemple, si vous utilisez pg_dump pour effectuer une sauvegarde de la table, vous ne souhaitez pas que les lignes soient omises de la sauvegarde. Pour éviter cela, définissez le paramètre de configuration row_security sur OFF pour l'utilisateur qui effectue la sauvegarde. Si des lignes sont filtrées en fonction de la sécurité au niveau des lignes, un message d'erreur s'affiche.

Masquer et anonymiser des données

En plus de masquer des données à l'aide d'une approche basée sur les vues, vous pouvez également masquer des données à l'aide de l'extension postgresql_anonymizer. Cette extension masque ou remplace les informations permettant d'identifier personnellement l'utilisateur ou les données commerciales sensibles dans une base de données PostgreSQL.

L'utilisation de l'extension par rapport à une approche basée sur les vues offre les avantages suivants :

  • Vous disposez de différentes fonctions de masquage telles que la substitution, la randomisation, la simulation, la pseudonymisation, le brassage partiel, le brassage, l'ajout de bruit et la généralisation.

  • Vous pouvez générer des données masquées significatives que vous pouvez ensuite utiliser pour les tests fonctionnels et le traitement des données.

  • Vous pouvez utiliser le langage de définition de données (LDD) PostgreSQL pour déclarer des règles de masquage et spécifier la stratégie d'anonymisation dans la définition de table.

Installer et configurer l'extension postgresql_anonymizer

Pour utiliser cette extension sur une instance Cloud SQL, procédez comme suit :

  1. Modifiez l'instance, puis définissez le flag cloudsql.enable_anon sur on. Pour en savoir plus sur la définition des indicateurs de base de données et pour découvrir les indicateurs de base de données compatibles avec l'extension, consultez Configurer des indicateurs de base de données.

  2. Si vous prévoyez d'utiliser des masques dynamiques et que les tables que vous souhaitez masquer ne se trouvent pas dans le schéma public, définissez l'indicateur anon.sourceschema sur le nom du schéma contenant ces tables. Pour les exemples de cette page, définissez l'option sur secure_schema.

  3. Créez l'extension dans la base de données en exécutant la commande suivante :

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

Une fois que vous avez installé et configuré l'extension, utilisez-la sur l'instance pour mettre en œuvre des stratégies d'anonymisation par masquage dynamique, masquage statique pi vidage anonyme.

Masquage dynamique

Utilisez le masquage dynamique pour définir des règles de masquage pour des utilisateurs spécifiques. Ces utilisateurs ne peuvent pas voir les informations permettant d'identifier personnellement l'utilisateur. À la place, ils voient des données masquées. Tous les autres utilisateurs voient les données non masquées. Cette méthode est utile dans les environnements de production lorsque vous ne souhaitez pas modifier les informations permettant d'identifier l'utilisateur, mais que vous les masquez uniquement pour certains utilisateurs.

Pour l'exemple du site Web de vente au détail, vous pouvez mettre en œuvre le masquage dynamique afin que l'administrateur puisse afficher les adresses e-mail et les mots de passe non masqués pour Jackson et Alice, mais que l'analyste ne puisse afficher que les données masquées.

--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)';

--Verify that the masked user is configured. The search_path must include
--the mask schema followed by the schema set in the anon.sourceschema flag.

SELECT rolconfig FROM pg_roles WHERE rolname = 'analyst_ro';
              rolconfig
--------------------------------------
 {"search_path=mask, secure_schema"}

--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" (open a new connection; 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 user_details;
 id | name  | age |       email_id         |    password
----+-------+-----+------------------------+-----------------
  1 | jack  |  34 | alisontodd@example.com | 13d249f2cb4127b
  2 | alice |  37 | amanda35@example.com   | 13d249f2cb4127b

--The masked user can't query the source table directly.

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

Lorsque vous commencez le masquage dynamique, l'extension crée une vue dans le schéma mask pour chaque table du schéma défini par le flag anon.sourceschema. Lorsque vous définissez un rôle comme MASKED, l'extension effectue les opérations suivantes :

  • Révoque les droits accordés directement au rôle sur le schéma source.
  • Accorde au rôle le droit USAGE sur le schéma mask et le droit SELECT sur chaque vue qu'il contient, y compris les vues des tables que le rôle ne pouvait pas interroger auparavant.
  • Définit le search_path du rôle sur le schéma mask, suivi du schéma source.

L'utilisateur masqué ne voit les données masquées que lorsqu'il interroge une table sans spécifier le nom du schéma, de sorte que le nom est résolu en vue dans le schéma mask. Les requêtes qui spécifient le nom du schéma, comme SELECT * FROM secure_schema.user_details, contournent le schéma mask et échouent avec une erreur d'autorisation. Le paramètre search_path est appliqué lorsque l'utilisateur se connecte. Les utilisateurs masqués doivent donc ouvrir une nouvelle connexion après que vous avez attribué le rôle.

Masquage statique

Utilisez le masquage statique pour supprimer les informations permettant d'identifier personnellement l'utilisateur d'une table, en fonction des critères définis dans les règles de masquage, et remplacez ces informations par des données masquées. Les utilisateurs ne peuvent pas récupérer les données non masquées. Cette méthode est utile dans les environnements de test lorsque vous souhaitez modifier les informations permettant d'identifier l'utilisateur et que vous ne souhaitez pas que les utilisateurs puissent consulter ces informations.

Pour l'exemple du site Web de vente au détail, vous pouvez mettre en œuvre un masquage statique afin qu'aucun utilisateur ne puisse consulter les adresses e-mail et les mots de passe non masqués pour Jack et Alice. À la place, ils ne voient que les données masquées.

--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 | 13d249f2cb4127b
  2 | alice |  37 | annebenitez@example.com         | 13d249f2cb4127b

Vidage anonyme

Utilisez des vidages anonymes pour exporter les données masquées dans un fichier SQL. Pour l'exemple de site Web de vente au détail, vous pouvez créer un fichier de dump pour les données masquées contenues dans la table user_details.

--Launch pg_dump_anon to apply earlier defined masking rules. pg_dump_anon
--reads the source table directly, so connect as a user that has the SELECT
--privilege on the table and that isn't labeled as MASKED.

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

Chiffrer des données

Bien que vous puissiez masquer les informations permettant d'identifier personnellement l'utilisateur, celles-ci sont stockées dans la base de données sous forme de texte brut. Un administrateur peut afficher ces informations.

Utilisez l'extension pgcrypto pour chiffrer les informations permettant d'identifier personnellement l'utilisateur avant de les stocker. Ainsi, seuls les utilisateurs disposant d'une clé de chiffrement valide peuvent déchiffrer les informations et les afficher en texte brut.

L'extension pgcrypto dispose d'un certain nombre de fonctions de hachage et de chiffrement.

Hachage

Un hachage est une fonction de chiffrement unidirectionnelle qui vous permet uniquement de chiffrer les informations personnelles. Cette méthode est utile pour stocker les mots de passe hachés et faire correspondre les mots de passe saisis par l'utilisateur avec les mots de passe hachés. Les mots de passe hachés ne sont jamais déchiffrés en texte brut.

Pour l'exemple de site Web de vente au détail, vous pouvez utiliser l'extension pgcrypto pour hacher le mot de passe de Jack avant de le stocker dans la table 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

Chiffrer

Utilisez une fonction de chiffrement pour chiffrer les informations permettant d'identifier personnellement l'utilisateur à l'aide d'une clé. Les utilisateurs ont ensuite besoin de cette clé pour déchiffrer les informations en texte brut. Ces informations sont utiles pour stocker des informations de carte de crédit et des coordonnées bancaires lorsque les applications souhaitent récupérer les informations permettant d'identifier personnellement l'utilisateur dans un format lisible.

Dans l'exemple du site Web de commerce de détail, le mot de passe et l'adresse e-mail de Jack sont chiffrés. Les utilisateurs disposant de la clé de chiffrement peuvent déchiffrer ces informations et les afficher en texte brut. Un message d'erreur s'affiche pour tous les autres utilisateurs.

--"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

Étapes suivantes

Découvrez les contrôles supplémentaires suivants que vous pouvez utiliser pour protéger les informations permettant d'identifier personnellement les utilisateurs contre les accès injustifiés :