Configurar o Secret Manager para seu ambiente

Cloud Composer 1 | Cloud Composer 2 | Cloud Composer 3

Nesta página, mostramos como usar o Gerenciador de secrets para armazenar com segurança conexões e secrets do Airflow.

Antes de começar

  • Para usar o Secret Manager, o ambiente do Cloud Composer precisa usar o Airflow 1.10.10 ou posterior e o Python 3.6 ou posterior.
  • O Python 2 não é compatível.

Configurar o Secret Manager para seu ambiente

Esta seção explica como configurar o Secret Manager para que você possa usar secrets com seu ambiente do Cloud Composer.

Ativar a API Secret Manager

Console

Enable the Secret Manager API.

Enable the API

gcloud

Enable the Secret Manager API:

gcloud services enable secretmanager.googleapis.com

Configurar o controle de acesso

É preciso configurar o controle de acesso para que o Airflow possa acessar secrets armazenados no Secret Manager.

Para fazer isso, a conta de serviço que acessa os secrets precisa ter um papel com a permissão secretmanager.versions.access. Por exemplo, o papel de Acessador de secrets do Gerenciador de secrets inclui essa permissão.

É possível conceder esse papel no nível Segredo, Projeto, Pasta ou Organização.

Use uma das seguintes opções:

Ativar a serialização do DAG

Em geral, use o back-end do Secret Manager somente nos métodos execute() dos seus operadores ou com os modelos Jinja. Por exemplo, é possível recuperar variáveis usando var.value.example_var.

O servidor da Web do Airflow é executado em uma conta de serviço diferente com permissões limitadas. Portanto, ele não pode acessar secrets no Secret Manager. Se o código DAG acessar secrets durante o processamento do DAG (não apenas de tarefas) e não for possível ajustá-lo para acessar secrets nos métodos execute(), ative o DAG serialização. Depois disso, o servidor da Web do Airflow usa DAGs processados e não precisa de acesso aos secrets.

Ativar e configurar o back-end do Gerenciador de secrets

  1. Substitua a seguinte opção de configuração do Airflow:

    Seção Chave Valor
    secrets backend airflow.providers.google.cloud.secrets.secret_manager.CloudSecretManagerBackend
  2. Adicione configurações opcionais substituindo o seguinte Airflow opção de configuração:

    Seção Chave Valor
    secrets backend_kwargs Veja a descrição a seguir.

    O valor backend_kwargs é a representação JSON do objeto backend_kwargs com os seguintes campos:

    • connections_prefix: prefixo do nome do secret a ser lido para conseguir conexões. O padrão é airflow-connections.
    • variables_prefix: prefixo do nome do secret a ser lido para receber. Variáveis. O padrão é airflow-variables.
    • gcp_key_path: caminho para o arquivo JSON de credenciais do Google Cloud. Se não for fornecido, a conta de serviço padrão será usada.
    • gcp_keyfile_dict: dicionário JSON de credenciais do Google Cloud. Mutuamente exclusivo com gcp_key_path.
    • sep: separador usado para concatenar connections_prefix e conn_id. O padrão é -.
    • project_id: ID do projeto do Google Cloud em que os secrets são armazenados.

    Por exemplo, o valor de backend_kwargs pode ser: {"project_id": "<project id>", "connections_prefix":"example-connections", "variables_prefix":"example-variables", "sep":"-"}.

Adicionar conexões e variáveis no Gerenciador de secrets

Crie secrets seguindo as etapas descritas em Como criar secrets e versões.

Variáveis

  • É necessário usar o formato [variables_prefix][sep][variable_name].
  • O valor padrão de [variables_prefix] é airflow-variables.
  • O separador padrão de [sep] é -.

Por exemplo, se o nome da variável for example-var, o nome do secret será airflow-variables-example-var.

Nomes de conexão

  • É necessário usar o formato [connection_prefix][sep][connection_name].
  • O valor padrão de [connection_prefix] é airflow-connections.
  • O separador padrão de [sep] é -.

Por exemplo, se o nome da conexão for exampleConnection, o nome do secret será airflow-connections-exampleConnection.

Valores de conexão

  • É necessário usar a representação do URI. Por exemplo, postgresql://login:secret@examplehost:9000.

  • O URI precisa ser codificado para uso em URL (porcentagem codificada). Por exemplo, uma senha que tenha um símbolo de espaço precisa ser codificada em URL da seguinte maneira: postgresql://login:secret%20password@examplehost:9000.

O Airflow tem um método de conveniência para gerar URIs de conexão. Um exemplo de como codificar um URL complexo com extras em JSON está disponível na documentação do Airflow.

Usar o Secret Manager com o Cloud Composer

Ao buscar variáveis e conexões, o Cloud Composer verifica primeiro o gerenciador de secrets. Se a variável ou conexão solicitada não for encontrada, o Cloud Composer verificará as variáveis de ambiente e o banco de dados do Airflow.

Ler variáveis usando modelos Jinja

O Secret Manager pode ser usado para ler variáveis Modelos Jinja para campos de operador com modelo (resolvido no ambiente de execução).

Para o secret airflow-variables-secret_filename:

file_name = '{{var.value.secret_filename}}'

Ler variáveis usando operadores personalizados e callbacks

Use o Gerenciador de secrets para ler variáveis em operadores personalizados ou métodos de callback dos operadores. A leitura de variáveis de DAGs internos pode afetar negativamente o desempenho. Portanto, use modelos Jinja se quiser usar variáveis nos DAGs.

Por exemplo, para o secret airflow-variables-secret_filename:

from airflow.models.variable import Variable
file_name = Variable.get('secret_filename')

Ler conexões

A menos que você esteja gravando um operador personalizado, raramente será necessário acessar conexões diretamente. A maioria dos ganchos recebe o nome da conexão como seu parâmetro de instanciação e deve recuperar as conexões do back-end do secret automaticamente quando as tarefas forem executadas.

Ler conexões diretamente pode ser útil para gravar seu próprio gancho.

Por exemplo, para a conexão airflow-connections-exampleConnection:

from airflow.hooks.base_hook import BaseHook
exampleConnection = BaseHook.get_connection('exampleConnection')

BaseHook.get_connection retorna um objeto Connection. É possível conseguir a representação da string de URI de uma conexão como esta:

exampleConnectionUri = BaseHook.get_connection('exampleConnection').get_uri()

A seguir