O que é atestado de convidado para VMs confidenciais?
O atestado de convidado ajuda a confirmar que seu ambiente de VM confidencial está protegido por um TEE (Trusted Execution Environment, ambiente de execução confiável) com suporte de hardware genuíno com recursos de segurança habilitados para isolamento e integridade.
Você pode usar o atestado de convidado para:
- Verifique se a VM confidencial é executada na plataforma de hardware esperada
- Verifique se a VM confidencial tem a inicialização segura habilitada. Essa configuração protege camadas inferiores da VM (firmware, carregador de inicialização, kernel) contra malware (rootkits, bootkits).
- Obter prova para uma terceira parte confiável de que a VM confidencial é executada em hardware confidencial
Observação
Para executar o atestado de convidado para VMs DCesv5 e ECesv5 com suporte do Intel TDX, um guia de instruções está disponível aqui. O uso da Autoridade de Confiança Intel requer registro na Intel.
Cenários
Os principais componentes e serviços envolvidos no atestado de convidado são:
- A carga de trabalho
- A biblioteca de atestados de convidado
- Hardware (para relatórios). Por exemplo, AMD-SEVSNP.
- O serviço Atestado do Microsoft Azure
- Resposta do token Web JSON
Os cenários operacionais típicos incorporam a biblioteca de clientes para fazer solicitações de atestado desta maneira.
Cenário: solicitação em carga de trabalho separada
Neste cenário de exemplo, as solicitações de atestado são feitas em uma carga de trabalho separada. As solicitações determinam se a VM confidencial é executada na plataforma de hardware correta antes de uma carga de trabalho ser iniciada.
Uma carga de trabalho (Cliente verificador da plataforma no diagrama) precisa se integrar à biblioteca de atestados e ser executada na VM confidencial para fazer o atestado. Depois que o programa faz uma solicitação à biblioteca de atestado, a carga de trabalho analisa a resposta para determinar se a VM é executada na plataforma de hardware correta e/ou na configuração de inicialização segura antes de iniciar a carga de trabalho confidencial.
Esse cenário é semelhante ao cenário a seguir. A principal diferença é como cada cenário atinge a mesma meta com base no local da solicitação.
Cenário: solicitação dentro da carga de trabalho
Neste cenário de exemplo, as solicitações de atestado são feitas dentro da carga de trabalho no início do programa. As solicitações verificam se a VM confidencial é executada na plataforma de hardware correta antes de uma carga de trabalho ser iniciada.
Esse cenário é semelhante ao cenário anterior. A principal diferença é como cada cenário atinge a mesma meta com base no local da solicitação.
A carga de trabalho do cliente precisa se integrar à biblioteca de atestados e ser executada dentro da VM confidencial. Depois que a carga de trabalho do cliente faz uma solicitação à biblioteca de atestado, a carga de trabalho do cliente analisa a resposta para determinar se a VM é executada na plataforma de hardware correta e/ou na configuração de inicialização segura antes de configurar a carga de trabalho confidencial por completo.
Cenário: handshake com terceira parte confiável
Neste cenário de exemplo, a VM confidencial deve provar que ela é executada em uma plataforma confidencial antes que uma terceira parte confiável se envolva. A VM confidencial apresenta um token de atestado à terceira parte confiável para iniciar a participação.
Alguns exemplos de participação são:
- A VM confidencial quer segredos de um serviço de gerenciamento de segredos.
- Um cliente deseja garantir que a VM confidencial será executada em uma plataforma confidencial antes de revelar dados pessoais para processamento pela VM confidencial.
O diagrama a seguir mostra o handshake entre uma VM confidencial e a terceira parte confiável.
O diagrama de sequência a seguir explica ainda mais o cenário de terceira parte confiável. A solicitação/resposta entre os sistemas envolvidos usa as APIs de biblioteca de atestados de convidado. A VM confidencial interage com o gerenciador de segredos para se inicializar usando os segredos recebidos.
APIs
A Microsoft fornece a biblioteca de atestados de convidado com APIs para fazer atestados, criptografar e descriptografar dados. Também há uma API para recuperar memória.
Você pode usar essas APIs nos vários cenários descritos anteriormente.
API de atestado
A API de atestado usa o objeto ClientParameters
como entrada e retorna um token de atestado descriptografado. Por exemplo:
AttestationResult Attest([in] ClientParameters client_params,
[out] buffer jwt_token);
Parâmetro | Informações |
---|---|
ClientParameters (type: object) |
Objeto que usa a versão (type: uint32_t ), o URI de locatário do atestado (type: unsigned character) e o conteúdo do cliente (type: unsigned character). O conteúdo do cliente é zero ou mais pares chave-valor de algum cliente ou metadados de cliente retornados no conteúdo de resposta. Os pares chave-valor precisam estar no formato de cadeia de caracteres JSON "{\"key1\":\"value1\",\"key2\":\"value2\"}" . Por exemplo, a chave-valor de atualização de atestado pode ser parecida com {\”Nonce\”:\”011510062022\”} . |
buffer |
Token Web JSON que contém informações de atestado. |
A API de atestado retorna um AttestationResult
(type: structure).
API de criptografia
A API de criptografia usa dados para criptografia e um token Web JSON como entrada. A API criptografa os dados usando a chave efêmera pública presente no token Web JSON. Por exemplo:
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);
Parâmetro | Explicação |
---|---|
encryption_type |
Nenhum. |
const unsigned char* jwt_token |
Token Web JSON que contém informações de atestado. |
const unsigned char* data |
Dados a serem criptografados |
uint32_t data_size |
Tamanho dos dados a serem criptografados. |
unsigned char** encrypted_data |
Dados criptografados. |
uint32_t* encrypted_data_size |
Tamanho dos dados criptografados. |
unsigned char** encryption_metadata |
Metadados de criptografia. |
uint32_t encryption_metadata_size |
Tamanho dos metadados de criptografia. |
A API de criptografia retorna um AttestationResult
(type: structure).
API de descriptografia
A API de descriptografia usa dados criptografados como entrada e os descriptografa usando a chave efêmera privada selada para a o TPM (Trusted Platform Module). Por exemplo:
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);
Parâmetro | Explicação |
---|---|
encryption_type |
Nenhum. |
const unsigned char* encrypted_data |
Dados a serem descriptografados. |
uint32_t encrypted_data_size |
Tamanho dos dados a serem descriptografados. |
const unsigned char* encryption_metadata |
Metadados de criptografia. |
unit32_t encryption_metadata_size |
Tamanho dos metadados de criptografia. |
unsigned char** decrypted_data |
Dados descriptografados. |
unit32_t decrypted_data_size |
Tamanho dos dados descriptografados. |
A API de descriptografia retorna um AttestationResult
(type: structure).
API de liberação
A API de liberação recupera memória retida pelos dados. Por exemplo:
Free([in] buffer data);
Parâmetro | Explicação |
---|---|
data |
Recupera memória retida pelos dados. |
A API de liberação não retorna nada.
Códigos do Erro
As APIs podem retornar os seguintes códigos de erro:
Código do erro | Descrição |
---|---|
1 | Erro ao inicializar a falha. |
2 | Erro ao analisar resposta. |
3 | Token Gerenciar identidades para recursos do Azure não encontrado. |
4 | A solicitação excedeu a quantidade de tentativas. |
5 | Falha na solicitação. |
6 | Falha no atestado. |
7 | Falha no envio de solicitação. |
8 | Parâmetro de entrada inválido. |
9 | Falha na validação dos parâmetros de atestado. |
10 | Falha na alocação de memória. |
11 | Falha ao obter informações do SO (sistema operacional). |
12 | Falha interna do TPM. |
13 | Falha na operação do TPM. |
14 | Falha na descriptografia do token Web JSON. |
15 | Erro de TPM de descriptografia do token Web JSON. |
16 | Resposta JSON inválida. |
17 | Certificado VCEK (Chave de Endosso de Chip com Versão Vazia). |
18 | Resposta vazia. |
19 | Corpo da solicitação vazio. |
20 | Falha na análise de relatórios. |
21 | Relatório vazio. |
22 | Erro ao extrair informações do token Web JSON. |
23 | Erro ao converter o token Web JSON em chave pública RSA. |
24 | Falha na inicialização da criptografia de EVP_PKEY. |
25 | Falha na criptografia de EVP_PKEY. |
26 | Erro de TPM de descriptografia de dados. |
27 | Erro ao analisar informações de DNS. |
Token Web JSON
Você pode extrair várias partes do token Web JSON para os diferentes cenários de API descritos anteriormente. Veja abaixo campos importantes para o recurso de atestado de convidado:
Declaração | Atributo | Valor de exemplo |
---|---|---|
- | x-ms-azurevm-vmid |
2DEDC52A-6832-46CE-9910-E8C9980BF5A7 |
Hardware AMD SEV-SNP | x-ms-isolation-tee |
sevsnpvm |
Hardware AMD SEV-SNP | x-ms-compliance-status (em x-ms-isolation-tee ) |
azure-compliant-cvm |
Inicialização Segura | secure-boot (em x-ms-runtime >vm-configuration ) |
true |
TPM Virtual | tpm-enabled (em x-ms-runtime >vm-configuration ) |
true |
TPM Virtual | kid (em 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"
}