Managed Airflow(Gen 3) | Managed Airflow(Gen 2) | Managed Airflow(レガシー Gen 1)
このページでは、Secret Manager を使用して Airflow の接続とシークレットを安全に格納する方法を説明します。
始める前に
- Secret Manager を使用するには、Managed Airflow 環境で Airflow 1.10.10 以降と Python 3.6 以降を使用する必要があります。
- Python 2 はサポートされていません。
環境に Secret Manager を構成する
このセクションでは、Managed Airflow 環境で Secret を使用できるように、Secret Manager を構成する方法について説明します。
Secret Manager API を有効にする
コンソール
Secret Manager API を有効にします。
API を有効にするために必要なロール
API を有効にするには、serviceusage.services.enable 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。詳しくは、ロールを付与する方法をご覧ください。
gcloud
Secret Manager API を有効にします。
API を有効にするために必要なロール
API を有効にするには、
権限を含む Service Usage 管理者 IAM
ロール(roles/serviceusage.serviceUsageAdmin)が必要です。serviceusage.services.enable詳しくは、ロールを付与する方法をご覧ください。
gcloud services enable secretmanager.googleapis.com
アクセス制御の構成
Airflow が Secret Manager に保存されているシークレットにアクセスできるように、アクセス制御を構成する必要があります。
そのためには、シークレットにアクセスするサービス アカウントに secretmanager.versions.access 権限を持つロールが付与されている必要があります。たとえば、Secret Manager Secret Accessor のロールにはこの権限が含まれています。
このロールは、シークレット レベル、プロジェクト レベル、フォルダレベル、または組織レベルで付与できます。
以下のいずれかの方法を選択します。
(推奨)お使いの環境のサービス アカウントにこのロールを付与します。
Airflow が Secret Manager にアクセスするサービス アカウントをオーバーライドします。
- サービス アカウントにこのロールを付与します。
backend_kwargsAirflow 構成オプションのgcp_key_pathパラメータを設定して、サービス アカウントの認証情報を含む JSON ファイルを指すようにします。
DAG のシリアル化を有効にする
一般に、Secret Manager のバックエンドは、演算子の execute() メソッド内から、または Jinja テンプレートでのみ使用してください。たとえば、変数は var.value.example_var を使用して取得できます。
Airflow ウェブサーバーは、権限が制限された別のサービス アカウントで実行されるため、Secret Manager のシークレットにアクセスできません。DAG コードが(タスクだけでなく)DAG の処理中にシークレットにアクセスし、execute() メソッド内からシークレットにアクセスするように調整できない場合は、DAG のシリアル化を有効にします。これにより、Airflow ウェブサーバーは処理された DAG を受け取り、Secret にアクセスする必要がなくなります。
Secret Manager バックエンドを有効にして構成する
次の Airflow 構成オプションをオーバーライドします。
セクション キー 値 secretsbackendairflow.providers.google.cloud.secrets.secret_manager.CloudSecretManagerBackendairflow.contrib.secrets.gcp_secrets_manager.CloudSecretsManagerBackend次の Airflow 構成オプションを オーバーライドして、オプションの設定を追加します。
セクション キー 値 secretsbackend_kwargs以下の説明をご覧ください。 backend_kwargs値は次の項目を持つbackend_kwargsオブジェクトの JSON 表現です。connections_prefix: 接続を取得するために読み取るシークレット名の接頭辞。デフォルトはairflow-connectionsです。variables_prefix: 変数を取得するために読み取るシークレット名の接頭辞。デフォルトのはairflow-variablesです。gcp_key_path: Google Cloud 認証情報の JSON ファイルへのパス(指定しない場合、デフォルトのサービス アカウントが使用されます)。gcp_keyfile_dict: Google Cloud 認証情報の JSON 辞書。gcp_key_pathとは相互に排他的です。sep:connections_prefixとconn_idを連結する際に使用する区切り文字。デフォルトは-です。project_id: シークレットが保存されている Google Cloud プロジェクト ID。
たとえば、
backend_kwargsの値は{"project_id": "<project id>", "connections_prefix":"example-connections", "variables_prefix":"example-variables", "sep":"-"}に設定できます。
Secret Manager で接続と変数を追加する
シークレットとバージョンの作成で説明されている手順に沿って、シークレットを作成します。
変数
[variables_prefix][sep][variable_name]形式を使用する必要があります。[variables_prefix]のデフォルト値はairflow-variablesです。- デフォルトの区切り文字
[sep]は-です。
たとえば、変数名が example-var の場合、シークレット名は airflow-variables-example-var です。
接続名
[connection_prefix][sep][connection_name]形式を使用する必要があります。[connection_prefix]のデフォルト値はairflow-connectionsです。- デフォルトの区切り文字
[sep]は-です。
たとえば、接続名が exampleConnection の場合、シークレット名は airflow-connections-exampleConnection です。
接続値
URI 表現を使用する必要があります。例:
postgresql://login:secret@examplehost:9000URI は URL エンコードされている必要があります(パーセントでエンコード)。たとえば、スペース記号を含むパスワードは、次のように URL エンコードする必要があります:
postgresql://login:secret%20password@examplehost:9000。
Airflow には、接続 URI を生成するための便利なメソッドがあります。JSON エクストラで複雑な URL をエンコードする例については、 Airflow ドキュメントをご覧ください。
Managed Airflow で Secret Manager を使用する
変数と接続を取得するとき、Managed Airflow は最初に Secret Manager をチェックします。リクエストされた変数または接続が見つからない場合、Managed Airflow は次に環境変数と Airflow データベースを確認します。
Jinja テンプレートを使用して変数を読み取る
Secret Manager では、テンプレート化された演算子フィールド(実行時に解決されます)について、JINJA テンプレートを使用して変数を読み取ることができます。
airflow-variables-secret_filename シークレットの場合:
file_name = '{{var.value.secret_filename}}'
カスタム演算子とコールバックを使用して変数の読み取る
Secret Manager を使用して、カスタム オペレータの変数やオペレータからのコールバック メソッドを読み取ることもできます。DAG 内から変数を読み取るとパフォーマンスが低下する可能性があるため、DAG で変数を使用する場合は Jinja テンプレートを使用します。
たとえば、airflow-variables-secret_filename シークレットの場合:
from airflow.models.variable import Variable
file_name = Variable.get('secret_filename')
読み取り接続
カスタム演算子を作成する場合を除き、接続に直接アクセスする必要はほとんどありません。ほとんどのフックは、インスタンス化パラメータとして接続名を取得し、タスクの実行時にシークレット バックエンドから接続を自動的に取得する必要があります。
独自のフックを作成する場合には、接続を直接読み取ることが有用な可能性があります。
たとえば、airflow-connections-exampleConnection 接続の場合:
from airflow.hooks.base_hook import BaseHook
exampleConnection = BaseHook.get_connection('exampleConnection')
BaseHook.get_connection は Connection オブジェクトを返します。接続の URI 文字列表現は、次のように取得できます。
exampleConnectionUri = BaseHook.get_connection('exampleConnection').get_uri()