Como usar o Secret Manager com Python

1. Visão geral

Neste codelab, o foco será o uso do Secret Manager no Python.

Com o Secret Manager, é possível armazenar, gerenciar e acessar secrets como blobs binários ou strings de texto. É possível visualizar o conteúdo do secret com as permissões apropriadas.

O Secret Manager funciona bem para armazenar informações de configuração, como senhas de bancos de dados, chaves de API ou certificados TLS, necessárias para um aplicativo no ambiente de execução.

O que você vai aprender

  • Como usar o Cloud Shell
  • Como instalar a biblioteca de cliente do Secret Manager para Python
  • Como criar e acessar secrets usando a biblioteca de cliente do Python
  • Como acessar secrets no Cloud Functions usando a biblioteca de cliente do Python

O que é necessário

  • Um projeto do Google Cloud
  • Um navegador, como o Chrome ou o Firefox
  • Familiaridade com Python 3

Pesquisa

Como você vai usar este tutorial?

Apenas leitura Ler e fazer os exercícios

Como você classificaria sua experiência com Python?

Iniciante Intermediário Proficiente

Como você classificaria sua experiência de uso dos serviços do Google Cloud?

Iniciante Intermediário Proficiente

2. Configuração e requisitos

Configuração de ambiente autoguiada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google Você pode atualizar a qualquer momento.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser alterado após a definição. O console do Cloud gera automaticamente uma string exclusiva. normalmente você não se importa com o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, que normalmente é identificado como PROJECT_ID. Se você não gostar do ID gerado, poderá gerar outro ID aleatório. Como alternativa, você pode tentar o seu próprio e ver se ele está disponível. Ela não pode ser alterada após essa etapa e permanecerá durante a duração do projeto.
  • Para sua informação, há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e não gerar faturamento além deste tutorial, exclua os recursos criados ou exclua o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Inicie o Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shell853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se você nunca iniciou o Cloud Shell antes, uma tela intermediária (abaixo da dobra) será exibida com a descrição dele. Se esse for o caso, clique em Continuar (e você não verá mais esse aviso). Esta é a aparência dessa tela única:

9c92662c6a846a5c.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

9f0e51b578fecce5.png

Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Praticamente todo o seu trabalho neste codelab pode ser feito em um navegador ou no seu Chromebook.

Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto já estará configurado com seu ID do projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar que você está autenticado:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Ativar a API Secret Manager

Antes de começar a usar a API Secret Manager, você precisa ativá-la. Com o Cloud Shell, é possível ativar a API com o seguinte comando:

gcloud services enable secretmanager.googleapis.com

A resposta será semelhante a esta:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

4. Como instalar a biblioteca de cliente do Secret Manager para Python

Instale a biblioteca de cliente do Secret Manager:

pip3 install --user google-cloud-secret-manager==2.10.0

5. Inicie o Python interativo

Para parte deste tutorial, você vai usar um interpretador de Python interativo chamado IPython (em inglês), que vem pré-instalado no Cloud Shell. Inicie uma sessão executando ipython no Cloud Shell:

ipython

Você verá algo como:

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

6. Como criar secrets

Um secret contém uma ou mais versões dele. Eles podem ser criados usando a linha de comando gcloud, mas também podem ser criados usando Python.

Para usar um secret, primeiro você precisa criá-lo com o nome e depois adicionar uma versão do secret, que é o valor dele.

Defina o ID do projeto no IPython:

PROJECT_ID = "<PROJECT_ID>"

Criar um secret

Copie o código a seguir na sessão do IPython:

from google.cloud import secretmanager

def create_secret(secret_id):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent project.
    parent = f"projects/{PROJECT_ID}"

    # Build a dict of settings for the secret
    secret = {'replication': {'automatic': {}}}

    # Create the secret
    response = client.create_secret(secret_id=secret_id, parent=parent, secret=secret)

    # Print the new secret name.
    print(f'Created secret: {response.name}')   

Chame a função para criar um novo secret com o nome my_secret_value:

create_secret("my_secret_value")

Você verá esta resposta:

Created secret: projects/<PROJECT_NUM>/secrets/my_secret_value

Adicionar uma versão do secret

Agora que o secret existe, é possível atribuir um valor a ele criando uma versão.

Copie o código a seguir na sessão do IPython:

def add_secret_version(secret_id, payload):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent secret.
    parent = f"projects/{PROJECT_ID}/secrets/{secret_id}"

    # Convert the string payload into a bytes. This step can be omitted if you
    # pass in bytes instead of a str for the payload argument.
    payload = payload.encode('UTF-8')

    # Add the secret version.
    response = client.add_secret_version(parent=parent, payload={'data': payload})

    # Print the new secret version name.
    print(f'Added secret version: {response.name}')   

Chame a função para criar e adicionar uma nova versão do secret:

add_secret_version("my_secret_value", "Hello Secret Manager")

Você verá esta resposta:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/1

Os secrets podem ter várias versões. Chame a função novamente com um valor diferente:

add_secret_version("my_secret_value", "Hello Again, Secret Manager")

Você verá esta resposta:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/2

Observe como a nova versão do secret é significativamente mais longa do que a original. Esse atributo será referenciado mais tarde.

7. Como acessar secrets

O acesso a uma versão do secret retorna o conteúdo dele, bem como metadados adicionais sobre a versão. Ao acessar uma versão do Secret, é possível especificar uma versão específica ou solicitar a versão mais recente especificando "latest".

Segredos devem ser mantidos em segredo. Armazenar as credenciais de bancos de dados como secrets e usá-las para autenticar ou armazenar certificações e usá-las. mas não imprima diretamente seus segredos, pois isso anula o propósito de mantê-los em segredo.

Você vai executar operações com nossos secrets, avaliando o valor deles sem imprimi-los diretamente. Em vez disso, você imprimirá um hash do valor do secret.

Copie o código a seguir na sessão do IPython:

def access_secret_version(secret_id, version_id="latest"):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the secret version.
    name = f"projects/{PROJECT_ID}/secrets/{secret_id}/versions/{version_id}"

    # Access the secret version.
    response = client.access_secret_version(name=name)

    # Return the decoded payload.
    return response.payload.data.decode('UTF-8')
    
import hashlib

def secret_hash(secret_value): 
  # return the sha224 hash of the secret value
  return hashlib.sha224(bytes(secret_value, "utf-8")).hexdigest()

Chame a função para recuperar o secret como um hash do valor dele:

secret_hash(access_secret_version("my_secret_value"))

Será exibida uma saída semelhante a um hash (o valor exato pode não corresponder a esta saída):

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Como você não especificou uma versão, o valor mais recente foi recuperado.

Chame a função adicionando o número de versão esperado para confirmar:

secret_hash(access_secret_version("my_secret_value", version_id=2))

A resposta será a mesma do último comando:

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Chame a função novamente, mas desta vez especificando a primeira versão:

secret_hash(access_secret_version("my_secret_value", version_id=1))

Desta vez, você verá um hash diferente, indicando uma saída diferente:

9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177

8. Como usar o Secret Manager com o Cloud Functions

É possível usar secrets em várias partes do Google Cloud. Nesta seção, você vai se concentrar no Cloud Functions, a oferta de computação sem servidor orientada a eventos do Google.

Se você tiver interesse em usar Python no Cloud Functions, siga o Codelab do Google Cloud Functions HTTP no Python.

Feche o IPython chamando a função exit:

exit

Você voltará ao Cloud Shell:

yourname@cloudshell:~ (<PROJECT_ID>)$

Antes de começar a usar a API Cloud Functions, você precisa ativá-la. Com o Cloud Shell, é possível ativar a API com o seguinte comando:

gcloud services enable cloudfunctions.googleapis.com cloudbuild.googleapis.com

Crie uma pasta para gerar nossa função, gerando arquivos vazios para gravar:

mkdir secret-manager-api-demo
cd secret-manager-api-demo
touch main.py
touch requirements.txt

Abra o editor de código no canto superior direito do Cloud Shell:

7651a97c51e11a24.png

Navegue até o arquivo main.py na pasta secret-manager-api-demo. É aqui que você vai colocar todo o código.

9. Como escrever uma função do Cloud para acessar secrets

Embora armazenar e recuperar valores de secrets da linha de comando ou do terminal IPython seja útil, é muito mais útil poder acessar esses secrets em uma função.

Com a função access_secret_version criada anteriormente, é possível usá-la como base para a função do Cloud.

Copie o seguinte código no arquivo main.py:

main.py

import os

from google.cloud import secretmanager

project_id = os.environ["PROJECT_ID"]

client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/my_secret_value/versions/latest"
response = client.access_secret_version(name=name)
my_secret_value = response.payload.data.decode("UTF-8")


def secret_hello(request):
    if "Again" in my_secret_value:
        return "We meet again!\n"

    return "Hello there.\n"

Antes de implantar a função, você precisa finalizar a configuração do ambiente. Para isso, é necessário configurar a dependência da função.

Crie um novo arquivo com o nome requirements.txt e adicione o pacote google-cloud-secret-manager a ele:

requirements.txt

google-cloud-secret-manager==2.10.0

Agora você tem uma pasta contendo apenas main.py e requirements.txt.

Como permitir acesso ao secret

Antes de implantar a função, você precisa permitir que o Cloud Functions acesse o secret.

Volte para o terminal:

c5b686edf94b5222.png

Conceda acesso à conta de serviço do Cloud Functions para acessar seu secret:

export PROJECT_ID=$(gcloud config get-value core/project)

gcloud secrets add-iam-policy-binding my_secret_value \
    --role roles/secretmanager.secretAccessor \
    --member serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com

Você verá esta resposta:

Updated IAM policy for secret [my_secret_value].
bindings:
- members:
  - serviceAccount:<PROJECT_ID>@appspot.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWiRUt2oB4=
version: 1

10. Como implantar a função do Cloud

Considerando a configuração nas seções anteriores, agora é possível implantar e testar a função do Cloud.

Dentro da pasta que contém apenas os dois arquivos que você criou, implante a função:

gcloud functions deploy secret_hello \
    --runtime python39 \
    --set-env-vars PROJECT_ID=${PROJECT_ID} \
    --trigger-http \
    --allow-unauthenticated

A seguinte resposta (truncada) será exibida:

Deploying function (may take a while - up to 2 minutes)...done.

...

entryPoint: secret_hello
httpsTrigger:
  url: https://<REGION>-<PROJECT_ID>.cloudfunctions.net/secret_hello
...
status: ACTIVE
...

Recupere o URL da função (metadados httpsTrigger.url) com o seguinte comando:

FUNCTION_URL=$(gcloud functions describe secret_hello --format 'value(httpsTrigger.url)')

Agora, teste se a função pode ser acessada com o valor de retorno esperado chamando sua função:

curl $FUNCTION_URL

Você verá esta resposta:

We meet again!

Essa função faz referência à versão mais recente do secret, que foi configurada para conter a string "novamente". Portanto, a função está funcionando conforme o esperado.

11. Parabéns!

Você aprendeu a usar a API Secret Manager com Python.

Limpar

Para evitar cobranças dos recursos usados neste tutorial na conta do Google Cloud, siga estas etapas:

  • No console do Cloud, acesse a página Gerenciar recursos.
  • Na lista de projetos, selecione seu projeto e clique em Excluir.
  • Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

Saiba mais

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.