Como usar o Secret Manager com Python

1. Visão geral

Neste codelab, você vai usar o Secret Manager em Python.

O Secret Manager permite 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.

Ele funciona bem para armazenar informações de configuração, como senhas de banco de dados, chaves de API ou certificados TLS necessários 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 o 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 É possível atualizar o local 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. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto.
  • Para sua informação, há um terceiro valor, um Número do 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 evitar cobranças além deste tutorial, exclua os recursos criados ou 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, vai ver uma tela intermediária abaixo da dobra com a descrição dele. Se esse for o caso, clique em Continuar e você não a verá novamente. 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 contém 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 comando a seguir no Cloud Shell para confirmar se 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, é necessário 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

Em parte deste tutorial, você vai usar um interpretador interativo chamado IPython, que já vem 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 ou Python.

Para usar um secret, primeiro crie-o com o nome dele e adicione uma versão, que é o valor.

Defina o ID do projeto no IPython:

PROJECT_ID = "<PROJECT_ID>"

Criar um secret

Copie o seguinte código na sua 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 chamado 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 seguinte código na sua 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 nosso secret é significativamente mais longa do que a original. Esse atributo será referenciado mais tarde.

7. Acessar secrets

O acesso a uma versão do secret retorna o conteúdo do secret, bem como metadados adicionais sobre a versão do secret. Ao acessar uma versão do secret, você pode especificar uma versão específica ou apenas pedir a mais recente especificando "latest".

Os secrets precisam ser mantidos em segredo. Armazene as credenciais do banco de dados como secrets e use-as para autenticar ou armazenar e usar certificações. Não imprima os secrets diretamente, porque isso prejudica o objetivo de mantê-los em segredo.

Você vai realizar operações nos nossos secrets, avaliando o valor deles sem imprimir diretamente. Em vez disso, você vai imprimir um hash do valor do secret.

Copie o seguinte código na sua 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"))

Você vai ver 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 da versão esperada para confirmar:

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

Você vai ver a mesma saída 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ê vai 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ê quiser usar Python no Cloud Functions, siga o codelab HTTP do Google Cloud Functions em Python.

Chame a função exit para fechar o IPython:

exit

Você vai 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 criar nossa função, criando 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 gravar uma função do Cloud para acessar secrets

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

Usando a função access_secret_version que você criou antes, é possível usá-la como base para sua função do Cloud.

Copie o código a seguir 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, finalize a configuração do ambiente. Isso exige que você configure a dependência da função.

Crie um arquivo chamado 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 com apenas um main.py e um requirements.txt.

Permitir o acesso ao seu 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

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

Na pasta que contém apenas os dois arquivos criados, implante a função:

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

Você vai ver a seguinte saída (truncada):

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 a 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 definida para conter a string "Again". Portanto, ela está funcionando como 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.