Notre partenaire HashiCorp a annoncé récemment la sortie de la version 1.7 de Vault, son produit de gestion des secrets dans des environnements low-trust.

Au menu :

  • Autopilot pour gérer automatiquement la stabilité des clusters qui utilisent le stockage intégré
  • Amélioration globale des performances et de la stabilité des clusters
  • IHM de gestion des secrets de bases de données
  • Passage GA de la Tokenization
  • Passage GA du moteur de secrets KMS

Ces deux dernières fonctionnalités sont fournies via le module Advanced Data Protection de Vault Enterprise. Le but de cet article est de présenter leur fonctionnement, et d’identifier des cas d’usages dans lesquels elles peuvent être utiles.

Information importante : j’utiliserais ici le terme de token pour désigner la valeur obtenue dans le cas de la tokenisation. J’utiliserais le terme token d’authentification pour parler des tokens obtenus lors de l’authentification.

Tokenization

Principe

En sécurité, le principe de la tokenization est de substituer une donnée sensible, comme un numéro de sécurité sociale, par une valeur non sensible appelée token. Contrairement aux techniques de chiffrement ou de hachage, il n’y a aucun lien mathématique entre un token et la valeur à laquelle il se substitue. Il est donc impossible d’obtenir la valeur d’origine à partir de son token.

La tokenization implémentée par le moteur de secrets Transform fournit un moyen de limiter le risque d’exposition de données sensibles lorsqu’elles sont traitées et stockées dans un système automatisé.

Prenons l’exemple d’une plateforme de paiement qui utilise un système de queue pour traiter les paiements de manière asynchrone, et qui doit respecter la norme PCI-DSS pour stocker des informations de paiement..


Le stockage du numéro de carte bancaire dans Vault, couplé à l’utilisation de policies strictes nous garantit que seul le service de paiement sera en mesure de lire la valeur. Et comme chaque secret enregistré dans ce moteur dispose d’un TTL (Time To Live)  qui lui est propre, la suppression du numéro de carte est garantie.

Info : on pourrait également utiliser le mécanisme de wrapping de Vault pour stocker le secret avec un TTL et obtenir un token d’authentification en échange. Mais dans ce cas, si un attaquant intercepte le token et qu’il a accès à Vault, il pourra récupérer la valeur sans être authentifié.

La tokenization peut également être utilisée pour un stockage sur de plus longues durées, pour un paiement récurrent par exemple. Dans ce cas, le token sera stocké dans une base de données à côté. On peut même le stocker sur le terminal de l’utilisateur, pour associer le moyen de paiement à l’appareil.

Configuration

Après avoir activé le moteur de secrets Transform, il faut créer un rôle qui permet la tokenization :

$ vault write transform/role/mobile-pay transformations=credit-card

$ vault write transform/transformations/tokenization/credit-card \
    allowed_roles=mobile-pay \
    max_ttl=2h

Le paramètre max_ttl limite la durée pendant laquelle les tokens créés seront valides, il doit être adapté au cas d’utilisation.

Utilisation

Le numéro de carte bancaire renseigné par l’utilisateur est stocké dans Vault par le backend, qui obtient en retour un token.

POST /transform/encode/mobile-pay
{
    "value": "1111-2222-3333-4444",
    "transformation": "credit-card",
    "ttl": "1h",
    "metadata": "Type=AMEX"
}

{
    "encoded_value": "eRwUjS2L9draZ9YrqcUyeDDGGPgB61i4nyDhYkw4rphDqHqRCvSgRDbL58Hk3JXLMn7T77uf2"
}

Les microservices auxquels on transmet le token peuvent obtenir des informations sur le secret sans le lire :

POST /transform/metadata/mobile-pay
{
    "value": "eRwUjS2L9draZ9YrqcUyeDDGGPgB61i4nyDhYkw4rphDqHqRCvSgRDbL58Hk3JXLMn7T77uf2"
}
 
{
    "expiration_time": "2021-04-30 20:11:36.744433584 +0000 UTC",
    "metadata": {
        "Type": "AMEX"
    }
}
 
POST /transform/validate/mobile-pay
{
    "value": "eRwUjS2L9draZ9YrqcUyeDDGGPgB61i4nyDhYkw4rphDqHqRCvSgRDbL58Hk3JXLMn7T77uf2"
}
 
{
    "valid": true
}

Enfin, le microservice qui contacte la banque du client pour effectuer la transaction récupère le numéro de carte bancaire :

POST /transform/decode/mobile-pay
{
    "value": "eRwUjS2L9draZ9YrqcUyeDDGGPgB61i4nyDhYkw4rphDqHqRCvSgRDbL58Hk3JXLMn7T77uf2"
}
 
{
    "decoded_value": "1111-2222-3333-4444"
}

Une fois la transaction terminée, le numéro de carte bancaire peut être supprimé par l’application. Si un problème applicatif fait que la valeur n’est pas supprimée, elle le sera automatiquement par Vault une fois son TTL expiré.

Limites

La principale limite de cette fonctionnalité est sa mise à l’échelle.  Dans le cas de la tokenization, chaque lecture / écriture d’un secret implique un accès au storage backend de Vault. Les performances sont donc limitées par celles du backend de stockage.

Pour contourner ce problème, il est possible d’utiliser une base de données externe (PostgreSQL ou MySQL) pour stocker les secrets tokenizés, mais cela implique un compromis en termes de sécurité.

Key Management Service

Principe

Pour les clients qui veulent rester maîtres de la génération et de la distribution de leurs clés de chiffrement, les cloud providers offrent la possibilité d’importer des clés existantes dans leurs systèmes de gestion des clés. C’est ce que l’on appelle le bring your own key (BYOK).

Sur AWS KMS par exemple, je peux importer ma clé privée avec l’API ImportKeyMaterial, et ensuite l’utiliser de la même manière que les clés gérées par AWS.

Seul le cloud provider est responsable de la sécurisation des clés de chiffrement qu’il génère et stocke. En revanche, dans le cadre du BYOK, cette responsabilité est partagée entre le provider et le client.

Traditionnellement, ces clés sont générées sur un PC vierge non connecté à internet. Ensuite, elles sont sauvegardées sur une clé USB chiffrée, qui elle-même est stockée dans un coffre-fort ignifugé. C’est un processus très lourd à gérer, et je ne parle même pas de la distribution de la clé.

Pour répondre à ce problème, HashiCorp développe le moteur de secrets Key Management. Ce moteur fournit une API pour générer des clés de chiffrement, les stocker dans Vault, et les distribuer sur plusieurs cloud providers.

Configuration

Comme d’habitude avec Vault, il faut commencer par activer le moteur de secrets. Ensuite, on configure les différents keyvaults sur lesquels les clés de chiffrement seront distribuées. Exemple de configuration d’un keyvault Azure :

$ vault write keymgmt/kms/my-azure-keyvault \
    key_collection="my-keyvault-52246b" \
    provider="azurekeyvault" \
    credentials=client_id="c0ff33c3-d073-40ba-a16e-9fb1d39e1973" \
    credentials=client_secret="COFFEE.2q-esz4~01d92OLOVE1974C6_t_" \
    credentials=tenant_id="c0ff3374-ba40-4725-ae1e-c8675309213c"

Utilisation

La première étape consiste à générer une nouvelle clé privée my-secure-key, qui sera stockée dans Vault :

$ vault write keymgmt/key/my-secure-key type="rsa-2048"
Success! Data written to: keymgmt/key/my-secure-key

Vault permet de lire les informations publiques de la clé pour chaque version de la clé, la liste des informations remontées dépend du type de clé. En revanche, Vault ne fournit aucun moyen de récupérer la valeur de la clé privée (même avec un token root).

$ vault read -format=json keymgmt/key/my-secure-key | jq '.data'
{
    "deletion_allowed": false,
    "latest_version": 1,
    "min_enabled_version": 1,
    "name": "my-secure-key",
    "type": "rsa-2048",
    "versions": {
        "1": {
            "creation_time": "2021-04-30T13:10:22.448542982Z",
            "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhki...\nqQIDAQAB\n-----END PUBLIC KEY-----\n"
        }
    }
}

Maintenant, nous pouvons distribuer cette nouvelle clé de manière sécurisée sur notre keyvault Azure, en spécifiant le type d’utilisation et le niveau de protection de la clé côté Azure. Le nom du keyvault (my-azure-keyvault) et de la clé (my-secure-key) sont précisés dans le chemin donné :

$ vault write keymgmt/kms/my-azure-keyvault/key/my-secure-key \
    purpose="encrypt,decrypt" \
    protection="hsm"

Enfin, la rotation de la clé privée et la distribution de la nouvelle version se font en une seule commande, c’est Vault qui se charge de synchroniser la clé sur les différents providers sur lesquels elle est distribuée :

$ vault write -f keymgmt/key/my-secure-key/rotate

Limites

Bien que le moteur KMS soit désormais stable, seul Azure est supporté pour la distribution des clés pour le moment. Le support d’AWS KMS est encore en bêta.

En théorie, Vault devrait pouvoir distribuer la même clé sur plusieurs cloud providers, mais en pratique nous sommes limités par les types de clés que ces derniers supportent. Au moment de l’écriture de cet article, seul l’import de clés RSA est possible sur Azure, et seul l’import de clés AES256 est possible sur AWS.

Conclusion

Dans la première partie, nous avons vu l’intérêt de la tokenization pour limiter l’exposition de données sensibles lors de leur traitement dans un système automatisé. Ensuite, la seconde partie a montré les difficultés liées à la mise en place d’une stratégie BYOK pour générer, stocker, et distribuer des clés de chiffrement de manière sécurisée.

Avec les moteurs de secrets Transform et KMS, Vault propose une réponse intéressante à ces besoins. Et bien sûr cela vient en plus de tous les avantages de la version open source :

  • Nombreuses méthodes d’authentification
  • API complète et documentée
  • Intégration avec Terraform
  • Log d’audit