XinCTO/aws : S3 chiffré avec IAM KMS

Ecrit le Sun, 24 June 2018 16:33:15 +0000
1208 mots 6 minutes

aws : S3 chiffré avec IAM KMS

En plus de l’accès filtré à un bucket amazon s3, il est possible de positionner du chiffrement sur la base de clés gérées dans IAM, voilà comment démarrer.

L’utilisation du cloud et de ses services passe toujours pas le questionnement des solutions de sécurité et de confidentialité. Le service populaire s3 chez AWS de gestion des fichiers permet de couvrir une palette importante d’usages, depuis l’accès totalement public jusqu’à l’accès authentifié et chiffré. Je vous propose de regarder rapidement le fonctionnement de la partie chiffrement, son articulation et l’implémentation en python boto3 pour les plus téméraires.

IAM

Le module d’identity management d’AWS est un incontournable, vous ne pouvez pas regarder les services sans y passer du temps afin d’affiner les identités, les autorisations, les droits et dans le cas présent les clés de chiffrement.

Utilisateur

Pour tester le service S3 chiffré, il vous faut un utilisateur défini dans l’IAM avec les droits sur le service S3. Si vous souhaitez aller vite, vous pouvez autoriser tous les droits sur S3 via la stratégie AmazonS3FullAccess, en fonction des usages il serait idéal d’affiner sur les droits de lecture, d’écriture, de parcours et de gestion des autorisations.

Cet utilisateur doit également disposer d’une clé d’accès qui sera utilisée dans le code via les API REST.

Clé de chiffrement

En bas du menu gauche de l’IAM vous avez accès à la gestion des clés de chiffrement. Autant les utilisateurs sont globaux, attention, les clés sont régionales. J’ai volontairement choisi de faire mes tests dans la région de Paris, autant faire local.

Une clé est définie par un alias, éventuellement une description, des administrateurs de la clé et des utilisateurs. Dans notre cas, il faut ajouter notre utilisateur IAM à la liste des utilisateurs de la clé. La clé est identifié techniquement (ID de la clé) qu’il faudra utiliser pour l’attribution de la propriété de chiffrement dans notre code.

La clé ainsi crée embarque les principes de chiffrement symétrique, la clé de chiffrement en tant que tel n’est pas accessible et totalement cachée dans les utilisations. Cette clé est crée par aws et stockée par aws, donc ce n’est pas un gage de sécurité puisque vous avez au même endroit vos fichiers (dans S3) et la clé (dans IAM KMS ). Si vous souhaitez un chiffrement externe, vous ne pourrez pas utiliser le principe de gestion intégrée aux services aws. Néanmoins, le service est en conformité avec FIPS 140-2 qui normalise tout ceci. Les mauvaises langues pourrons ainsi penser que l’oncle Sam dispose de l’accès aux clés de chiffrement… autre débat que je laisse à plus tard autour d’un verre éventuellement.

S3

Dans le service S3, on crée un bucket spécifique à notre usage, dans les propriétés on pourra positionner le chiffrement par défaut de celui-ci. Soit on chiffre par défaut tous les fichiers en son sein, soit on laisse au niveau de chaque fichier la possibilité d’être chiffré. C’est le même principe que pour l’exposition publique de notre bucket et de ses fichiers constitutifs. A noter qu’un bucket chiffré ne pourra contenir de fichier non chiffré et par conséquent accessible sans autorisation particulière, c’est donc la solution la plus sécurisée car elle évite les erreurs de manipulation et les oublis.

Parmi les choix disponibles pour le chiffrement, on sélectionnera le chiffrement géré dans AWS-KMS (c’est à dire lié à l’IAM), l’autre choix AES-256 permet de demander un chiffrement mais globalisé et géré au niveau du service S3 uniquement (je ne vois pas bien l’intérêt de celui-ci, n’hésitez pas à m’éclairer). Avec le choix KMS on indiquera également la clé à utiliser. Une seule clé est associable à ce niveau, si vous souhaitez utiliser plusieurs clés, il faudra effectuer l’opération au niveau unitaire.

En rendant le bucket (ou les fichiers) accessible au public (à positionner dans les autorisations), il sera alors possible de voir (dans un navigateur) les différents modules de sécurité qui sont utilisés : AccessDenied si le compte ne dispose pas de l’accès ou que l’objet n’est pas public, Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature si l’utilisateur ne dispose pas de la clé de chiffrement.

En parcourant votre bucket et ses fichiers, vous trouverez les informations sur le positionnement du chiffrement (server side encryption), son type (AWS-KMS) et la clé utilisée.

Python avec boto3

C’est bien beau tout cela, mais dans le code ça ressemble à quoi ?

Authentification

Votre code python (à adapter aux autres langages bien sûr) doit embarquer ses credentials, ils peuvent également être déposé dans un fichier à la racine du compte ou encore mieux dans les mécanismes automatique de d’aws. Faisons simple et mettons tout cela dans le code pour l’exemple.

import boto3
import botocore

s3 = boto3.resource('s3',
    aws_access_key_id="BKIAJ62BX****URDIQBA",
    aws_secret_access_key="FmBziA/aVJYm**********3uquCmUGK/Ly3kXzf2"
)

La clé et son id sont à récuperer dans l’IAM au moment de la création, l’id est récupérable, mais pas la clé, attention à bien la conserver donc. La ressource s3 ainsi créée va nous permettre de manipuler nos objets dans le service, par exemple :

print("buckets:")
for bucket in s3.buckets.all():
    print(bucket.name)

Récupération d’un fichier

Afin de copier un fichier vers son client, rien de spécifique n’est requis, la mécanique d’autorisation et de chiffrement est directement embarquée dans IAM KMS, c’est tout l’intérêt :

   s3.Bucket('xincto-test-key').download_file('fold01/dataviz.jpg', 'a.jpg')

Ici, on récupère dans le bucket xincto-test-key, le fichier nommé dataviz.jpg positionné dans le répertoire fold01 et on le copie en local dans le fichier a.jpg

Si mon utilisateur ne dispose pas de l’accès à la clé de chiffrement dans IAM KMS, une erreur de type AccessDenied sera levée lors de l’appel à la fonction de lecture. Vous pouvez le tester rapidement en supprimant l’accès au niveau de l’IAM, la prise en compte étant immédiate, on se rend très vite compte de l’impact.

Dépose d’un fichier

C’est lors des opérations d’upload de fichier que la complexité du code réside, notamment si vous souhaitez déposer un fichier chiffré sur un bucket qui ne l’est pas :

 1s3.Bucket('xincto-test-key')
 2.upload_file('a.jpg', 'fold01/a.jpg',
 3             ExtraArgs={
 4                 'ACL': 'public-read',
 5                 "Metadata": {
 6                     "mykey": "my value"
 7                 },
 8                 'ContentType': 'image/jpeg',
 9                 'SSEKMSKeyId': '71f53ffA-3ea2-40ed-b1b7-df9f81c17aaf',
10                 'ServerSideEncryption': 'aws:kms'
11             }
12)

Ici, on déponse le fichier a.jpg sur le même bucket et dans le même répertoire, sans changer son nom (ligne #1). Dans les arguments complémentaires (#2} on positionne :

  • #4 : l’accès public (pas d’intérêt puisque le fichier est chiffré)
  • #6 : une clé/valeur
  • #8 : le type de l’objet pour une interprétation par un client sans se poser de question sur la nature, plutôt utile sur le fichier accédés par un navigateur en mode public donc
  • #9 : l’id de la clé de chiffrement
  • #10 : le type de chiffrement à utiliser sur le fichier

Conclusion

Voilà de quoi démarrer vos usages de S3 en mode chiffré, c’est sécurisant de savoir que le risque d’accéder aux données est réduit, notamment ceci devrait grandement limiter les accès ouverts à des buckets s3 par inadvertance et la divulgation des données contenues.

Attention néanmoins au fait que vous mettez les clés et le cadenas chez l’hébergeur et devez par conséquent lui faire confiance. C’est de toute façon mieux que de tout laisser non chiffré car autorise un niveau de granularité sur l’accès plus fin via l’IAM.


Photo from Markus Spiske