Antes de enviar informações confidenciais a uma instância de máquina virtual, o aplicativo pode verificar a identidade da máquina usando tokens de identidade da instância assinados pelo Google. Cada instância tem um JSON Web Token (JWT) exclusivo que inclui detalhes sobre ela, bem como a assinatura RS256 do Google. Seus aplicativos podem verificar a assinatura dos certificados OAuth2 públicos do Google para confirmar a identidade da instância com que estabeleceram uma conexão.
O Compute Engine gera tokens assinados somente quando uma instância os solicita a partir dos metadados dela. Uma instância só pode acessar o próprio token exclusivo, e não os de outras instâncias.
Verifique as identidades das suas instâncias nos seguintes cenários:
- Quando a instância é iniciada pela primeira vez, os aplicativos podem precisar confirmar se a identidade dela é válida antes de transmitirem informações confidenciais para a instância.
- Quando as políticas exigem o armazenamento das credenciais fora do ambiente do Compute Engine, e você as envia regularmente às instâncias para uso temporário. Os aplicativos podem confirmar a identidade das instâncias sempre que precisarem transmitir credenciais.
Os métodos de autenticação de instâncias do Google têm os seguintes benefícios:
- O Compute Engine cria um token exclusivo sempre que uma instância o solicita. Cada token expira em até uma hora. É possível configurar seus aplicativos para aceitarem um token de identidade somente uma vez. Isso reduz o risco de que o token seja reutilizado por um sistema não autorizado.
- As chaves privadas do Google e os certificados OAuth2 públicos são alternados diariamente para reduzir a superfície de ataques contra essas assinaturas.
- Os tokens de metadados assinados usam o padrão aberto do setor RFC 7519 e a camada de identidade OpenID Connect 1.0 (links em inglês). Assim, as ferramentas e bibliotecas atuais funcionam perfeitamente com os tokens de identidade.
Antes de começar
- Para usar os exemplos de linha de comando deste guia, siga estas etapas:
- Instale ou atualize a ferramenta de linha de comando gcloud para a versão mais recente.
- Defina uma região e uma zona padrão.
- Para usar os exemplos de API deste guia, configure o acesso à API.
- Entenda como recuperar os valores de metadados da instância.
- Entenda os conceitos básicos dos JSON Web Tokens para saber como usá-los nos seus aplicativos.
- Entenda como criar e ativar contas de serviço nas instâncias. Elas precisam ter uma conta de serviço associada para recuperar tokens de identidade. Para esse processo, não é necessário ter uma permissão IAM na conta de serviço.
Como verificar a identidade de uma instância
Em alguns cenários, os aplicativos precisam verificar a identidade de uma instância em execução no Compute Engine antes de transmitir dados confidenciais para ela. Vejamos um exemplo comum, em que há uma instância do Compute Engine chamada "VM1" e um sistema em execução fora dele chamado "Host1". A VM1 pode se conectar ao Host1 e validar a identidade da instância com o seguinte processo:
A VM1 estabelece uma conexão segura com o Host1 por meio do protocolo de conexão protegida que você escolher, como HTTPS.
A VM1 solicita o token de identidade exclusivo do servidor de metadados e especifica o público do token. Nesse exemplo, o valor do público é o URI do Host1. A solicitação ao servidor de metadados inclui o URI do público para que o Host1 possa confirmar o valor mais tarde, durante a etapa de verificação do token.
O Google gera um novo token exclusivo de identidade da instância no formato JWT e o fornece à VM1. O payload do token inclui vários detalhes sobre a instância, além do URI do público. Confira uma descrição completa sobre o Conteúdo do token na seção correspondente.
A VM1 envia o token de identidade ao Host1 por meio da conexão segura atual.
O Host1 decodifica o token de identidade para receber os valores do cabeçalho e payload.
Para verificar se o token é assinado pelo Google, o Host1 compara o valor do público e a assinatura do certificado com o certificado público do Google.
Se o token for válido, o Host1 prossegue com a transmissão e encerra a conexão quando terminar. O Host1 e quaisquer outros sistemas precisam solicitar um novo token para conexões posteriores com a VM1.
Como receber o token de identidade da instância
Quando recebe uma solicitação para fornecer o token de identidade, a instância de máquina virtual o solicita do servidor de metadados. Para isso, ela usa o processo normal de recebimento de metadados da instância. Por exemplo, você pode usar um dos seguintes métodos:
cURL
Crie uma solicitação curl
e inclua um valor no parâmetro audience
.
Também é possível incluir o parâmetro format
para especificar se quiser ou não incluir detalhes do projeto e da instância na carga útil. Se estiver usando o formato full
, é possível incluir o parâmetro licenses
para especificar se quer ou não incluir códigos de licença no payload.
$ curl -H "Metadata-Flavor: Google" \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=[AUDIENCE]&format=[FORMAT]&licenses=[LICENSES]'
em que:
[AUDIENCE]
é o URI exclusivo aceito pela instância e pelo sistema que verifica a identidade dela. Por exemplo, o público pode ser um URL da conexão entre os dois sistemas;[FORMAT]
é o parâmetro opcional que especifica se os detalhes do projeto e da instância estão incluídos ou não no payload. Especifiquefull
para incluir essas informações no payload oustandard
para omiti-las. O valor padrão éstandard
. Leia sobre o formato do token de identidade para saber todos os detalhes;[LICENSES]
é um parâmetro opcional que especifica se os códigos de licença para imagens associadas a essa instância são ou não incluídos no payload. EspecifiqueTRUE
para incluir essas informações ouFALSE
para omiti-las do payload. O valor padrão éFALSE
. Não tem efeito a menos queformat
sejafull
.
O servidor de metadados usa o algoritmo RS256 (em inglês) para responder a essa solicitação com um token da Web JSON assinado. Ele inclui uma assinatura do Google e informações adicionais no payload. É possível enviar esse token para outros sistemas e aplicativos para que eles possam verificá-lo e confirmar a identidade da instância.
Python
Você pode enviar uma solicitação simples da sua instância ao servidor de metadados usando os métodos na biblioteca Python requests
. O exemplo a seguir solicita e imprime um token de identidade da instância. Ele é exclusivo para a instância que faz a solicitação.
import requests
AUDIENCE_URL = 'http://www.example.com'
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
FORMAT = 'full'
LICENSES = 'TRUE'
# Construct a URL with the audience and format.
url = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience={}&format={}&licenses={}'
url = url.format(AUDIENCE_URL, FORMAT, LICENSES)
# Request a token from the metadata server.
r = requests.get(url, headers=METADATA_HEADERS)
# Extract the token from the response.
token = r.text
print(token)
O servidor de metadados usa o algoritmo RS256 para responder a essa solicitação com um JSON Web Token assinado. Ele inclui uma assinatura do Google e informações adicionais no payload. É possível enviar esse token para outros sistemas e aplicativos para que eles possam verificá-lo e confirmar a identidade da instância.
Como verificar o token
Depois que seu aplicativo receber um token de identidade de uma instância do Compute Engine, ele poderá verificá-lo usando o processo a seguir.
Receba o token da instância de máquina virtual, faça a decodificação dele usando um decodificador RS256 JWT e leia o conteúdo do cabeçalho para conseguir o valor
kid
.Compare o token com o certificado público do Google para verificar se ele está assinado. Cada certificado público tem um valor
kid
que corresponde aokid
no cabeçalho do token.Se o token for válido, compare o conteúdo do payload com os valores esperados. Se o payload do token incluir detalhes sobre a instância e o projeto, o aplicativo poderá verificar os valores
instance_id
,project_id
ezone
. Eles são uma tupla globalmente exclusiva que confirma se o aplicativo se comunica com a instância correta no projeto esperado.
É possível decodificar e verificar o token usando a ferramenta que você quiser. No entanto, um método comum é usar as bibliotecas do seu idioma. Por exemplo, é possível usar o método verify_token
da biblioteca Google OAuth 2.0 (em inglês) para Python. O verify_token
combina o valor kid
ao certificado apropriado, verifica a assinatura, confere a reivindicação de público e retorna o conteúdo do payload do token.
# Import libraries for token verification
import google.auth.transport.requests
from google.oauth2 import id_token
# Receive token from VM over an SSL connection
token = …
…
# Verify token signature and store the token payload
request = google.auth.transport.requests.Request()
payload = id_token.verify_token(token, request=request, audience=audience)
…
Depois de verificar o token e seu conteúdo, o aplicativo poderá se comunicar com essa instância em uma conexão segura e depois encerrar a conexão quando terminar. Para as conexões posteriores, solicite um novo token da instância e volte a verificar a identidade dela.
Conteúdo do token
O token de identidade da instância contém três partes principais:
Cabeçalho
O cabeçalho inclui o valor kid
para identificar quais certificados OAuth2 públicos são necessários para verificar a assinatura. Ele também inclui o valor alg
para confirmar que a assinatura foi gerada usando o algoritmo RS256 (em inglês).
{
"alg": "RS256",
"kid": "511a3e85d2452aee960ed557e2666a8c5cedd8ae",
}
Payload
O payload contém a reivindicação de público aud
. Se a instância especificou format=full
ao solicitar o token, o payload também inclui reivindicações sobre a instância de máquina virtual e o projeto dela.
Ao solicitar um token de formato completo, a especificação de licenses=TRUE
também incluirá reivindicações sobre as licenças associadas à instância.
{
"iss": "[TOKEN_ISSUER]",
"iat": [ISSUED_TIME],
"exp": [EXPIRED_TIME],
"aud": "[AUDIENCE]",
"sub": "[SUBJECT]",
"azp": "[AUTHORIZED_PARTY]",
"google": {
"compute_engine": {
"project_id": "[PROJECT_ID]",
"project_number": [PROJECT_NUMBER],
"zone": "[ZONE]",
"instance_id": [INSTANCE_ID],
"instance_name": "[INSTANCE_NAME]",
"instance_creation_timestamp": [CREATION_TIMESTAMP],
"license_id": [
"[LICENSE_1]",
...
"[LICENSE_N]"
]
}
}
}
em que:
[TOKEN_ISSUER]
é um URL que identifica o emissor do token. No Compute Engine, esse valor éhttps://accounts.google.com
;[ISSUED_TIME]
é um carimbo de data/hora Unix que indica quando o token foi emitido. Esse valor é atualizado sempre que a instância solicita um token do servidor de metadados;[EXPIRED_TIME]
é um carimbo de data e hora Unix que indica quando o token expira;[AUDIENCE]
é o URI exclusivo aceito pela instância e pelo sistema que verifica a identidade dela. Por exemplo, o público pode ser um URL da conexão entre os dois sistemas;[SUBJECT]
é o assunto do token, que é o código exclusivo da conta de serviço associada à instância;[AUTHORIZED_PARTY]
é a parte à qual foi emitido o código do token, que é o código exclusivo da conta de serviço associada à instância;[PROJECT_ID]
é o código do projeto em que você criou a instância;[PROJECT_NUMBER]
é o número exclusivo do projeto em que a instância foi criada;[ZONE]
é a zona em que a instância está localizada;[INSTANCE_ID]
é o código exclusivo da instância a que esse token pertence. Esse código é único e não pode ser reutilizado;[INSTANCE_NAME]
é o nome da instância a que esse token pertence. Ele pode ser reutilizado por várias instâncias ao longo do tempo. Por isso, use o valorinstance_id
para identificar um código exclusivo da instância;[CREATION_TIMESTAMP]
é um carimbo de data/hora Unix que indica quando a instância foi criada;[LICENSE_1]
até[LICENSE_N]
são os códigos de licença para imagens associadas a essa instância.
Veja o exemplo de payload a seguir:
{
"iss": "https://accounts.google.com",
"iat": 1496953245,
"exp": 1496956845,
"aud": "https://www.example.com",
"sub": "107517467455664443765",
"azp": "107517467455664443765",
"google": {
"compute_engine": {
"project_id": "my-project",
"project_number": 739419398126,
"zone": "us-west1-a",
"instance_id": "152986662232938449",
"instance_name": "example",
"instance_creation_timestamp": 1496952205,
"license_id": [
"1000204"
]
}
}
}
Assinatura
O Google gera a assinatura por Base64url, codificando o cabeçalho e o payload, além de concatenar os dois valores. É possível comparar esse valor com os certificados OAuth2 públicos para verificar o token.
A seguir
- Saiba mais sobre as práticas recomendadas para organizações empresariais.