Partage via


Qu’est-ce que l’attestation d’invité pour les machines virtuelles confidentielles ?

L’attestation d’invité vous aide à confirmer que votre environnement de machine virtuelle confidentielle est sécurisé par un véritable environnement d’exécution approuvé soutenu par le matériel (TEE) avec des fonctionnalités de sécurité activées pour l’isolation et l’intégrité.

Vous pouvez utiliser l’attestation d’invité pour :

  • Assurez-vous que la machine virtuelle confidentielle s’exécute sur la plateforme matérielle attendue
  • Vérifiez que le démarrage sécurisé de la machine virtuelle confidentielle est activé. Ce paramètre protège les couches inférieures de la machine virtuelle (microprogramme, chargeur de démarrage, noyau) contre les programmes malveillants (rootkits, bootkits).
  • Obtenir des preuves pour une partie de confiance que la machine virtuelle confidentielle s’exécute sur du matériel confidentiel

Remarque

Pour effectuer une attestation d’invité pour les machines virtuelles DCesv5 et ECesv5 sauvegardées par Intel TDX, un guide pratique est disponible ici. L’utilisation d’Intel Trust Authority nécessite l’inscription auprès d’Intel.

Scénarios

Les principaux composants et services impliqués dans l’attestation d’invité sont les suivants :

  • La charge de travail
  • Bibliothèque d’attestations invité
  • Matériel (pour la création de rapports). Par exemple, AMD-SEVSNP.
  • Service d’Attestation Microsoft Azure
  • Réponse de jeton web JSON

Diagram of guest attestation scenario for a confidential VM.

Les scénarios opérationnels classiques incorporent la bibliothèque client pour effectuer des demandes d’attestation comme suit.

Scénario : demande dans une charge de travail distincte

Dans cet exemple de scénario, les demandes d’attestation sont effectuées dans une charge de travail distincte. Les demandes déterminent si la machine virtuelle confidentielle s’exécute sur la plateforme matérielle appropriée avant le lancement d’une charge de travail.

Une charge de travail (client de vérificateur de plateforme dans le diagramme) doit s’intégrer à la bibliothèque d’attestations et s’exécuter à l’intérieur de la machine virtuelle confidentielle pour effectuer l’attestation. Une fois le programme demandé à la bibliothèque d’attestations, la charge de travail analyse la réponse pour déterminer si la machine virtuelle s’exécute sur la plateforme matérielle correcte et/ou le paramètre de démarrage sécurisé avant de lancer la charge de travail sensible.

Diagram of an attestation request being made in a separate workload.

Ce scénario est semblable au scénario suivant. La principale différence est la façon dont chaque scénario atteint le même objectif en fonction de l’emplacement de la requête.

Scénario : demande à partir d’une charge de travail interne

Dans cet exemple de scénario, les demandes d’attestation sont effectuées à l’intérieur de la charge de travail au début du programme. Les demandes vérifient si la machine virtuelle confidentielle s’exécute sur la plateforme matérielle appropriée avant le lancement d’une charge de travail.

Ce scénario est semblable au scénario précédent. La principale différence est la façon dont chaque scénario atteint le même objectif en fonction de l’emplacement de la requête.

La charge de travail du client doit s’intégrer à la bibliothèque d’attestations et s’exécuter à l’intérieur de la machine virtuelle confidentielle. Une fois la charge de travail client envoyée à la bibliothèque d’attestations, la charge de travail client analyse la réponse pour déterminer si la machine virtuelle s’exécute sur la plateforme matérielle correcte et/ou le paramètre de démarrage sécurisé avant de configurer entièrement la charge de travail sensible.

Diagram of an attestation request being made from within a workload inside a confidential VM.

Scénario : négociation de la partie de confiance

Dans cet exemple de scénario, la machine virtuelle confidentielle doit prouver qu’elle s’exécute sur une plateforme confidentielle avant qu’une partie de confiance ne s’engage. La machine virtuelle confidentielle présente un jeton d’attestation à la partie de confiance pour démarrer l’engagement.

Voici quelques exemples d’engagements :

  • La machine virtuelle confidentielle souhaite des secrets à partir d’un service de gestion des secrets.
  • Un client souhaite s’assurer que la machine virtuelle confidentielle s’exécute sur une plateforme confidentielle avant de révéler des données personnelles à la machine virtuelle confidentielle pour le traitement.

Le diagramme suivant montre la négociation entre une machine virtuelle confidentielle et la partie de confiance.

Diagram of an attestation request being made in a relying party scenario.

Le diagramme de séquence suivant explique davantage le scénario de la partie de confiance. La demande/réponse entre les systèmes impliqués utilise les API de bibliothèque d’attestation invité. La machine virtuelle confidentielle interagit avec le gestionnaire de secrets pour démarrer elle-même à l’aide des secrets reçus.

Diagram of the relying party VM with a secrets manager service.

API

Microsoft fournit à la bibliothèque d’attestation invité des API pour effectuer des attestations, chiffrer et déchiffrer des données. Il existe également une API pour récupérer la mémoire.

Vous pouvez utiliser ces API pour les différents scénarios décrits précédemment.

Attester l’API

L’API Attester accepte l’objet ClientParameters comme entrée et retourne un jeton d’attestation déchiffrée. Par exemple :

AttestationResult Attest([in] ClientParameters client_params,  

  				 [out] buffer jwt_token); 
Paramètre Information
ClientParameters (type : objet) Objet qui accepte la version (type : uint32_t), l’URI du locataire d’attestation (type : caractère non signé) et la charge utile du client (type : caractère non signé). La charge utile du client est zéro ou plusieurs paires clé-valeur pour les métadonnées client ou client retournées dans la charge utile de réponse. Les paires clé-valeur doivent être au format "{\"key1\":\"value1\",\"key2\":\"value2\"}" de chaîne JSON. Par exemple, la valeur clé d’actualisation de l’attestation peut ressembler à {\”Nonce\”:\”011510062022\”} .
buffer Jeton web JSON qui contient des informations d’attestation.

L’API Attester retourne un AttestationResult (type : structure).

Chiffrer l’API

L’API Chiffrer prend les données à chiffrer et un jeton web JSON comme entrée. L’API chiffre les données à l’aide de la clé éphémère publique présente dans le jeton web JSON. Par exemple :

AttestationResult Encrypt(

  [enum] encryption_type, 

  [in] const unsigned char* jwt_token, 

  [in] const unsigned char* data, 

  [in] uint32_t data_size, 

  [out] unsigned char** encrypted_data, 

  [out] uint32_t* encrypted_data_size, 

  [out] unsigned char** encryption_metadata,  

  [out] uint32_t encryption_metadata_size); 
Paramètre Explication
encryption_type Aucune.
const unsigned char* jwt_token Jeton web JSON qui contient des informations d’attestation.
const unsigned char* data Données à chiffrer
uint32_t data_size Taille des données à chiffrer.
unsigned char** encrypted_data Données chiffrées.
uint32_t* encrypted_data_size Taille des données chiffrées.
unsigned char** encryption_metadata Métadonnées de chiffrement.
uint32_t encryption_metadata_size Taille des métadonnées de chiffrement.

L’API Chiffrer retourne un AttestationResult (type : structure).

Déchiffrer l’API

L’API Déchiffrer prend des données chiffrées comme entrée et déchiffre les données à l’aide de la clé éphémère privée qui est scellée au module de plateforme sécurisée (TPM). Par exemple :

AttestationResult Decrypt([enum] encryption_type, 

  [in] const unsigned char* encrypted_data, 

  [in] uint32_t encrypted_data_size, 

  [in] const unsigned char* encryption_metadata, 

  [in] unit32_t encryption_metadata_size, 

  [out] unsigned char** decrypted_data,  

  [out] unit32_t decrypted_data_size); 
Paramètre Explication
encryption_type Aucune.
const unsigned char* encrypted_data Données à déchiffrer.
uint32_t encrypted_data_size Taille des données à déchiffrer.
const unsigned char* encryption_metadata Métadonnées de chiffrement.
unit32_t encryption_metadata_size Taille des métadonnées de chiffrement.
unsigned char** decrypted_data Données déchiffrées.
unit32_t decrypted_data_size Taille des données déchiffrées.

L’API Déchiffrer retourne un AttestationResult (type : structure).

API gratuite

L’API Gratuit récupère la mémoire conservée par les données. Par exemple :

Free([in] buffer data); 
Paramètre Explication
data Récupérez la mémoire conservée par les données.

L’API Gratuit ne retourne rien.

Codes d’erreur

Les API peuvent retourner les codes d’erreur suivants :

Code d’erreur Description
1 Erreur lors de l’initialisation de l’échec.
2 Réponse d’analyse d’erreur.
3 Jeton des Identités managées pour les ressources Azure introuvable.
4 La requête a dépassé les nouvelles tentatives.
5 Échec de la requête.
6 Échec de l’attestation.
7 Échec de l’envoi de la requête.
8 Paramètre d'entrée non valide.
9 Échec de la validation des paramètres d’attestation.
10 L'allocation de mémoire a échoué.
11 Nous n’avons pas pu obtenir les informations du système d’exploitation.
12 Échec interne du module TPM.
13 Échec de l’opération TPM.
14 Échec du déchiffrement du jeton web JSON.
15 Erreur TPM de déchiffrement de jeton web JSON.
16 Réponse JSON non valide.
17 Certificat VCEK (Chip Endorsement Key) avec version vide.
18 Réponse vide.
19 Corps de la requête vide.
20 Signaler l’échec de l’analyse.
21 État vide.
22 Erreur lors de l’extraction des informations de jeton web JSON.
23 Erreur lors de la conversion du jeton web JSON en clé publique RSA.
24 L’initialisation du chiffrement EVP_PKEY a échoué.
25 Le chiffrement EVP_PKEY a échoué.
26 Erreur TPM de déchiffrement des données.
27 Erreur lors de l’analyse des informations DNS.

JSON Web Token

Vous pouvez extraire différentes parties du jeton web JSON pour les différents scénarios d’API décrits précédemment. Voici des champs importants pour la fonctionnalité d’attestation d’invité :

Revendication Attribut Exemple de valeur
- x-ms-azurevm-vmid 2DEDC52A-6832-46CE-9910-E8C9980BF5A7
Matériel AMD SEV-SNP x-ms-isolation-tee sevsnpvm
Matériel AMD SEV-SNP x-ms-compliance-status (sous x-ms-isolation-tee) azure-compliant-cvm
Démarrage sécurisé secure-boot (sous x-ms-runtime>vm-configuration) true
Module de plateforme sécurisée (TPM) virtuel tpm-enabled (sous x-ms-runtime>vm-configuration) true
Module de plateforme sécurisée (TPM) virtuel kid (sous x-ms-runtime>keys) TpmEphemeralEncryptionKey
{
  "exp": 1653021894,
  "iat": 1652993094,
  "iss": "https://sharedeus.eus.test.attest.azure.net",
  "jti": "<value>",
  "nbf": 1652993094,
  "secureboot": true,
  "x-ms-attestation-type": "azurevm",
  "x-ms-azurevm-attestation-protocol-ver": "2.0",
  "x-ms-azurevm-attested-pcrs": [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    11,
    12,
    13
  ],
  "x-ms-azurevm-bootdebug-enabled": false,
  "x-ms-azurevm-dbvalidated": true,
  "x-ms-azurevm-dbxvalidated": true,
  "x-ms-azurevm-debuggersdisabled": true,
  "x-ms-azurevm-default-securebootkeysvalidated": true,
  "x-ms-azurevm-elam-enabled": true,
  "x-ms-azurevm-flightsigning-enabled": false,
  "x-ms-azurevm-hvci-policy": 0,
  "x-ms-azurevm-hypervisordebug-enabled": false,
  "x-ms-azurevm-is-windows": true,
  "x-ms-azurevm-kerneldebug-enabled": false,
  "x-ms-azurevm-osbuild": "NotApplicable",
  "x-ms-azurevm-osdistro": "Microsoft",
  "x-ms-azurevm-ostype": "Windows",
  "x-ms-azurevm-osversion-major": 10,
  "x-ms-azurevm-osversion-minor": 0,
  "x-ms-azurevm-signingdisabled": true,
  "x-ms-azurevm-testsigning-enabled": false,
  "x-ms-azurevm-vmid": "<value>",
  "x-ms-isolation-tee": {
    "x-ms-attestation-type": "sevsnpvm",
    "x-ms-compliance-status": "azure-compliant-cvm",
    "x-ms-runtime": {
      "keys": [
        {
          "e": "AQAB",
          "key_ops": [
            "encrypt"
          ],
          "kid": "HCLAkPub",
          "kty": "RSA",
          "n": "<value>"
        }
      ],
      "vm-configuration": {
        "console-enabled": true,
        "current-time": 1652993091,
        "secure-boot": true,
        "tpm-enabled": true,
        "vmUniqueId": "<value>"
      }
    },
    "x-ms-sevsnpvm-authorkeydigest": "<value>",
    "x-ms-sevsnpvm-bootloader-svn": 2,
    "x-ms-sevsnpvm-familyId": "<value>",
    "x-ms-sevsnpvm-guestsvn": 1,
    "x-ms-sevsnpvm-hostdata": "<value>",
    "x-ms-sevsnpvm-idkeydigest": "<value>",
    "x-ms-sevsnpvm-imageId": "<value>",
    "x-ms-sevsnpvm-is-debuggable": false,
    "x-ms-sevsnpvm-launchmeasurement": "<value>",
    "x-ms-sevsnpvm-microcode-svn": 55,
    "x-ms-sevsnpvm-migration-allowed": false,
    "x-ms-sevsnpvm-reportdata": "<value>",
    "x-ms-sevsnpvm-reportid": "<value>",
    "x-ms-sevsnpvm-smt-allowed": true,
    "x-ms-sevsnpvm-snpfw-svn": 2,
    "x-ms-sevsnpvm-tee-svn": 0,
    "x-ms-sevsnpvm-vmpl": 0
  },
  "x-ms-policy-hash": "<value>",
  "x-ms-runtime": {
    "keys": [
      {
        "e": "AQAB",
        "key_ops": [
          "encrypt"
        ],
        "kid": "TpmEphemeralEncryptionKey",
        "kty": "RSA",
        "n": "<value>"
      }
    ]
  },
  "x-ms-ver": "1.0"
}

Étapes suivantes