Protection des informations sensibles avec les UDFs et les procédures stockées sécurisées

Pour garantir que les informations sensibles sont dissimulées aux utilisateurs qui ne devraient pas y avoir accès, vous pouvez utiliser le mot-clé SECURE lors de la création d’une fonction définie par l’utilisateur (UDF) et d’une procédure stockée.

Cette rubrique décrit comment vous pouvez :

Dans ce chapitre :

Limiter la visibilité d’une UDF ou d’une définition de procédure

Pour une UDF ou une procédure stockée, vous pouvez empêcher les utilisateurs de voir les détails de la définition. Lorsque vous spécifiez que l’UDF ou la procédure est sécurisée, ces détails ne sont visibles que pour les utilisateurs autorisés, autrement dit pour les utilisateurs auxquels est attribué un rôle qui possède la fonction.

Par exemple, pour une fonction ou une procédure sécurisée, les informations omises pour les utilisateurs non autorisés comprennent les éléments suivants :

  • Corps (le code du gestionnaire qui comprend sa logique)

  • Liste des importations

  • Nom du gestionnaire

  • Liste des packages

Les utilisateurs non autorisés seront toujours en mesure de voir les informations qui comprennent les éléments suivants :

  • Types de paramètres

  • Type de retour

  • Langue du gestionnaire

  • Traitement des nuls

  • Volatilité

Pour plus d’informations sur l’attribution de rôles, voir GRANT ROLE et Aperçu du contrôle d’accès.

Avec une fonction ou une procédure sécurisée, un utilisateur non autorisé (un utilisateur qui n’a pas reçu de rôle propriétaire de la fonction ou de la procédure) ne peut pas voir la définition de la fonction ou de la procédure lorsqu’il utilise l’un des éléments suivants :

Notez que les fonctions et procédures dont les gestionnaires sont écrits en Java, Python ou Scala autorisent la clause IMPORTS, qui importe le code ou les fichiers de données des zones de préparation Snowflake. L’utilisation du mot-clé SECURE n’a aucun effet sur la visibilité ou l’accès à ces zones de préparation.

En outre, pour les fonctions et procédures dont les gestionnaires sont écrits en Java, Python ou Scala, la sécurisation des fonctions et procédures garantit qu’elles sont exécutées dans des bacs à sable distincts, de sorte qu’aucune ressource n’est partagée entre elles.

Pour plus d’informations sur l’utilisation du mot-clé SECURE, voir Création d’une UDF ou d’une procédure stockée sécurisée.

Limitation de la visibilité des données sensibles d’une UDF.

Dans les UDFs, vous pouvez empêcher les utilisateurs de voir des données qui devraient être masquées en sécurisant les UDF. Pour ce faire, utilisez le mot-clé SECURE lorsque vous créez ou modifiez l’UDF.

Les UDF doivent être définies comme sécurisées lorsqu’elles sont spécifiquement conçues pour la confidentialité des données, c’est-à-dire pour limiter l’accès aux données sensibles qui ne doivent pas être exposées à tous les utilisateurs des tables sous-jacentes.

Vous ne devez pas sécuriser une UDF lorsqu’elle est définie pour la commodité de l’interrogation, par exemple lorsqu’elle est créée pour simplifier l’interrogation de données pour lesquelles les utilisateurs n’ont pas besoin de comprendre la représentation sous-jacente des données. En effet, l’optimiseur de requêtes Snowflake, lorsqu’il évalue les UDFs sécurisés, contourne les optimisations utilisées pour les UDFs classiques. Cela pourrait réduire les performances de la requête pour les UDFs sécurisés.

Pour limiter la visibilité des données sous-jacentes d’une UDF, utilisez le mot-clé SECURE lors de sa création ou de sa modification. Pour plus d’informations, voir Création d’une UDF ou d’une procédure stockée sécurisée.

Comment les données peuvent devenir visibles

Certaines des optimisations internes des UDFs, notamment une optimisation appelée pushdown, nécessitent l’accès aux données sous-jacentes dans les tables de base. Cet accès peut permettre aux données qui sont cachées aux utilisateurs de l’UDF d’être affichées indirectement au moyen de méthodes programmatiques. Dans certaines situations, un utilisateur peut être en mesure de déduire des informations sur des lignes qu’il ne peut pas voir directement.

Les UDFs sécurisées n’utilisent pas ces optimisations, ce qui garantit que les utilisateurs n’ont même pas accès indirectement aux données sous-jacentes. Pour plus d’informations sur le pushdown, voir Optimisation du pushdown et visibilité des données.

Astuce

Lorsque vous décidez d’utiliser ou non un UDF sécurisé, vous devez tenir compte de l’objectif de l’UDF et peser le pour et le contre entre confidentialité/sécurité des données et performance des requêtes.

De plus, si vos données sont suffisamment sensibles pour que vous décidiez que les accès via un type d’objet (tel que des UDFs) doivent être sécurisés, alors vous devriez fortement envisager de vous assurer que les accès via d’autres types d’objets (tels que les vues) le sont également.

Par exemple, si vous autorisez seulement les UDFs sécurisés à accéder à une table donnée, alors toutes les vues que vous autorisez à accéder à la même table devraient probablement être aussi sécurisées.

Comment les UDFs sécurisées protègent les données

Comme décrit dans Optimisation du pushdown et visibilité des données, l’optimisation du pushdown peut réorganiser les filtres qui déterminent le traitement d’une requête. Si l’optimisation réorganise les filtres d’une manière qui permet à un filtre général de fonctionner avant que le ou les filtres appropriés utilisés pour sécuriser les données soient appliqués, les détails sous-jacents pourraient être exposés. Par conséquent, la solution consiste à empêcher l’optimiseur d’effectuer un « pushdown » de certains types de filtres (plus généralement, d’empêcher l’optimiseur d’utiliser certains types d’optimisations, y compris, mais sans s’y limiter, le pushdown du filtre) si ces optimisations ne sont pas sûres.

Déclarer un UDF comme « sécurisé » indique à l’optimiseur de ne pas effectuer de « pushdown » de certains filtres (plus généralement, de ne pas utiliser certaines optimisations). Cependant, la prévention de certains types d’optimisations peut avoir un impact sur la performance.

Meilleures pratiques pour la protection de l’accès aux données sensibles

Les UDFs sécurisés empêchent les utilisateurs d’être éventuellement exposés aux données des lignes de tables filtrées par la fonction. Toutefois, il existe d’autres moyens par lesquels un propriétaire de données risque d’exposer par inadvertance des informations sur les données sous-jacentes si les UDFs ne sont pas correctement construits. Dans cette section, nous abordons certains pièges à éviter.

Éviter d’exposer les valeurs des colonnes générées par séquence

Une pratique courante pour générer des clés de substitution est d’utiliser une séquence ou une colonne d’auto-incrémentation. Si ces clés sont exposées à des utilisateurs qui n’ont pas accès à toutes les données sous-jacentes, l’utilisateur pourrait deviner les détails de la distribution de données sous-jacente.

Par exemple, supposons que nous ayons une fonction get_widgets_function() qui expose la colonne ID. Si un ID est généré à partir d’une séquence, alors un utilisateur de get_widgets_function() pourrait déduire le nombre total de widgets créés entre les horodatages de création de deux widgets auxquels l’utilisateur a accès. Imaginez la requête et le résultat suivants :

select * from table(get_widgets_function()) order by created_on;

------+-----------------------+-------+-------+-------------------------------+
  ID  |         NAME          | COLOR | PRICE |          CREATED_ON           |
------+-----------------------+-------+-------+-------------------------------+
...
 315  | Small round widget    | Red   | 1     | 2017-01-07 15:22:14.810 -0700 |
 1455 | Small cylinder widget | Blue  | 2     | 2017-01-15 03:00:12.106 -0700 |
...
Copy

En se basant sur les résultats, l’utilisateur pourrait soupçonner que 1 139 widgets (1455 - 315) ont été créés entre le 7 et le 15 janvier. Si ces informations sont trop sensibles pour être exposées aux utilisateurs d’une fonction, vous pouvez utiliser l’une des options suivantes :

  • N’exposez pas la colonne générée par séquence dans le cadre de la fonction.

  • Utilisez des identificateurs aléatoires (comme ceux générés par UUID_STRING) plutôt que des valeurs générées par séquence.

  • Floutez programmatiquement les identificateurs.

Limiter la visibilité de la taille des données analysées

Pour les requêtes contenant des fonctions sécurisées, Snowflake n’expose pas la quantité de données analysées (en termes d’octets ou de micro-partitions) ni la quantité totale de données. Le but est de protéger les informations des utilisateurs qui n’ont accès qu’à un sous-ensemble des données.

Toutefois, les utilisateurs pourraient toujours être capables de faire des observations sur la quantité de données sous-jacentes en fonction des caractéristiques de performance des requêtes. Par exemple, une requête qui dure deux fois plus longtemps pourrait traiter deux fois plus de données. Bien que ces observations soient au mieux approximatives, il est préférable que ce genre d’informations ne soit pas exposé dans certains cas.

Dans ces cas, vous devriez matérialiser les données par utilisateur/rôle plutôt que d’exposer aux utilisateurs les fonctions sur les données de base. Dans le cas de la table widgets décrite dans cette rubrique, une table serait créée pour chaque rôle ayant accès aux widgets. Chacune de ces tables ne contiendrait que les widgets accessibles par ce rôle, et un rôle se verrait accorder l’accès à sa table. Cela est beaucoup plus compliqué que d’utiliser une fonction unique, mais pour les situations de très haute sécurité, cela peut être justifié.

Autoriser l’accès à la table de base pour les utilisateurs d’un compte spécifique

Lorsque vous utilisez des UDFs sécurisés avec le partage de données, la fonction CURRENT_ACCOUNT peut être utilisée pour autoriser les utilisateurs d’un compte spécifique à accéder aux lignes d’une table de base.

Note

Lorsque vous utilisez les fonctions CURRENT_ROLE et CURRENT_USER avec des UDFs sécurisées qui seront partagées avec des comptes Snowflake, Snowflake renvoie une valeur NULL pour ces fonctions. La raison en est que le propriétaire des données partagées ne contrôle généralement pas les utilisateurs ou les rôles du compte avec lequel les UDF sont partagées.

UDFs sécurisées et politiques de masquage

Si vous utilisez une UDF, que l’UDF soit ou non une UDF sécurisée, dans une politique de masquage, assurez-vous que le type de données de la colonne, l’UDF et la politique de masquage correspondent.

Pour plus d’informations, voir Fonctions définies par l’utilisateur dans une politique de masquage.

Création d’une UDF ou d’une procédure stockée sécurisée

Vous pouvez sécuriser une UDF ou une procédure en utilisant le mot clé SECURE lors de sa création ou de sa modification.

Pour créer ou convertir une UDF afin de la sécuriser, spécifiez SECURE lors de l’utilisation de ce qui suit :

Pour créer une procédure de manière à la sécuriser, spécifiez SECURE lors de l’utilisation de ce qui suit :

Déterminer si une UDF ou une procédure est sécurisée

Vous pouvez déterminer si une fonction ou une procédure est sécurisée en utilisant la commande SHOW FUNCTIONS ou SHOW PROCEDURES. Les commandes renvoient une table avec une colonne IS_SECURE dont la valeur est Y pour sécurisé et N pour non sécurisé.

Le code de l’exemple suivant renvoie une table de propriétés pour une fonction MYFUNCTION.

show functions like 'MYFUNCTION';
Copy

Affichage des détails de la fonction sécurisée dans le profil de requête

Les éléments internes d’une fonction sécurisée ne sont pas exposés dans Profil de requête (dans l’interface Web). C’est aussi le cas pour le propriétaire de la fonction sécurisée, puisque des non-propriétaires peuvent avoir accès au profil de requête d’un propriétaire.