Skip to content
Last updated

カスタムスクリプトでシークレットを使用する方法

Treasure Dataでは、シークレット情報を環境変数内に隠すことをお勧めします。このベストプラクティスにより、他の人がシークレット情報にアクセスできるコードを誤ってプッシュすることを避けられます。

ローカル環境でPython仮想環境を作成する

Pythonは、独自のサイトディレクトリを持つ軽量な仮想環境を作成するためのvenvを提供しています。または、pipを使用して同じ環境を作成することもできます。

依存関係のインストール

  1. gistに移動します。

  2. 以下をダウンロードします:

  • requirements.txt
  • constraints.txt

コマンドラインからの例:

$ python -m venv .venv
$ source .venv/bin/activate
(.venv)$ pip install -r requirements.txt -c constraints.txt
  1. venv仮想環境を使用すると、ローカル環境で同じパッケージを使用して開発できます。

このアプローチでは、オペレーティングシステムの不一致は解決されません。例えば、Debianで実行されている本番環境と、WindowsまたはmacOS Xの開発環境では、apt-getのようなOS依存のコマンドを実行するときにエラーが発生する可能性があります。

PythonでTreasure Data Workflowをテストする

ローカル環境でワークフロー全体を実行したい場合は、Digdagを代替として使用できます。

Treasure WorkflowはDigdagと同じではありません。

Pythonオペレーターにパラメータを渡す

py>オペレーターにパラメータを渡す方法は以下のとおりです:

Digdag引数の例

py_scripts/examples.pyという名前のPythonスクリプトが以下のようにあると仮定します:

examples.py
def print_arg(msg):
    print(f"Message is {msg}")

以下の例のように、simple_with_argタスクからmessage引数を渡すことができます:

+simple_with_arg:
  py>: py_scripts.examples.print_arg
  msg: "Hello World"
  docker:
    image: "treasuredata/customscript-python:3.12.11-td0"

複数の引数を渡すには、関数に引数を追加し、Digdag引数にも追加します。

Digdag引数をPythonにシームレスに渡すことができますが、キーワード引数**kwargsを使用すると、意図しない変数が渡される可能性があります。例えば、Docker変数は辞書{"image": "treasuredata/customscript-python:3.12.11-td0"}として渡される可能性があります。Treasure Dataでは、Python関数で明示的な引数を使用することをお勧めします。

Digdagとpy>オペレーター間で意図しない競合が発生する可能性があります。以下のようにDigdag変数を設定したと仮定します:

_export:
  td:
    database: my_db

+simple_with_arg2:
  py>: py_scripts.examples.print_arg_td
  msg: "Hello World"
  docker:
    image: "treasuredata/customscript-python:3.12.11-td0"

以下のようにtd引数を持つPython関数print_arg_tdを使用します:

examples.py
def print_arg_td(msg, td=None):
    print(f"'msg' is {msg} and 'td' is {td}")

エクスポートされたtd変数は常に渡されるため、td変数は決して_None_であってはなりません。例えば、{"database": "my_db"}が渡される変数になるはずです。これにより、辞書と文字列のような型の不一致が発生する可能性があります。Treasure Dataでは、Digdagの予約済み引数の使用を避け、代わりにtd変数を使用することをお勧めします。例:

  • td.endpoint

  • td.apikey

  • td.use_ssl

  • td.proxy.enabled

  • td.proxy.host

  • td.proxy.port

  • td.proxy.password

  • td.proxy.user

Digdagは、例えば文字列から整数のように、意図しない型に変換する場合があります。Treasure Dataでは、Python関数内で型を評価または明示的に変換することをお勧めします。

参照:https://docs.digdag.io/workflow_definition.md#using-variables

環境変数

環境変数は、py>オペレーターにパラメータを渡すもう1つのオプションです。環境変数は、安全な情報やシークレットを渡すのに適しています。

シークレットと環境変数には8192文字の制限があります。

例えば、Treasure Dataにsimple_with_envタスクがある場合:

+simple_with_env:
  py>: py_scripts.examples.print_env
  _env:
    MY_ENV_VAR: "hello"
  docker:
    image: "treasuredata/customscript-python:3.12.11-td0"

os.environを通じてMY_ENV_VARにアクセスします。例:

import os

def print_env():
    print(f'Env var is {os.environ["MY_ENV_VAR"]}')

シークレット情報を使用する必要がある場合、例えばTreasure Data APIキーやAWSシークレットキーなどの場合、環境変数を使用することが重要です。

Digdagにはシークレット情報を保存する機能があります。td workflow secretsサブコマンドを実行すると、シークレットはDigdagまたはTreasure Workflowデータベースに保存されます。

td.apikeyという名前のシークレットを設定したと仮定します。このシークレットはpy>オペレーターに渡すことができます。例:

+simple_with_env2:
  py>: py_scripts.examples.access_td
  _env:
    TD_API_KEY: ${secret:td.apikey}
  docker:
    image: "treasuredata/customscript-python:3.12.11-td0"

py_scripts/examples.pyは以下のようになります:

import os

def access_td():
    apikey = os.environ["TD_API_KEY"]
    # Do awesome execution

通常のDigdag引数からシークレットを渡そうとすると、シークレットはシークレットDBから取得されません。例えば、以下のようなタスクがある場合:

+simple_with_env_ng:
  py>: py_scripts.examples.access_td_ng
  apikey: ${secret:td.apikey}
  docker:
    image: "treasuredata/customscript-python:3.12.11-td0"

代わりに以下のスクリプトを使用する必要があります:

def access_td_ng(apikey):
    print(apikey)
    # Always shows "${secret:td.apikey}" insted of actual API key like "1234/XXXX"

Digdag変数

PythonスクリプトでDigdag変数を読み取りたい場合は、以下の例のようにDigdag.env.paramsを使用できます:

def read_workflow_env(msg):
    import digdag
    print(digdag.env.params["my_msg"])

import Digdagコマンドは、スクリプトがDigdag py>オペレータータスクとして実行されている場合にのみ実行できます。インポートエラーを回避したい場合は、以下のように「try-except構文」を記述する必要があります:

try:
  import digdag
  digdag.env.store({"feature_query": feature_query})
except ImportError:
  pass