digdag secrets を楽して環境変数にマップしたい


digdag のバージョンは v0.9.31

困りごと

digdag secrets で登録した秘密な情報を、embulk の liquid ファイルや docker の entrypoint.sh から参照したいことがある。

その場合、digdag secrets の変数を直接参照することはできないので、_env を使って環境変数にマップしてあげて参照できるようにする必要がある。

embulk.yml.liquid
out:
  type: bigquery
  auth_method: json_key
  json_keyfile:
    content: ${env.secret_gcp_credential}
sample.dig
+task1:
  _env:
    secret_gcp_credential: ${secret:gcp.credential}
    secret_aws_access_key_id: ${secret:aws.access_key_id}
    secret_aws_secret_access_key: ${secret:aws.secret_access_key}
  sh>: embulk run embulk.yml.liquid

しかし現行(v0.9.31)のdigdagでは、この _env 設定を全てのタスクに書かなければならない。global なタスクを作ってもダメで、_export に書こうとしてもダメ。辛い。

sample.dig
+task1:
  _env:
    secret_gcp_credential: ${secret:gcp.credential}
    secret_aws_access_key_id: ${secret:aws.access_key_id}
    secret_aws_secret_access_key: ${secret:aws.secret_access_key}
  sh>: embulk run embulk.yml.liquid
+task2:
  _env:
    secret_gcp_credential: ${secret:gcp.credential}
    secret_aws_access_key_id: ${secret:aws.access_key_id}
    secret_aws_secret_access_key: ${secret:aws.secret_access_key}
  sh>: embulk run embulk.yml.liquid
+task3:
  _env:
    secret_gcp_credential: ${secret:gcp.credential}
    secret_aws_access_key_id: ${secret:aws.access_key_id}
    secret_aws_secret_access_key: ${secret:aws.secret_access_key}
  sh>: embulk run embulk.yml.liquid

こちらに同じ辛みを抱えている Issue があるdigdag#937

!include で楽をする

別ファイルに切り出して !include を使えば、多少は短くなる。

sub/secrets.dig
_env:
  secret_gcp_credential: ${secret:gcp.credential}
  secret_aws_access_key_id: ${secret:aws.access_key_id}
  secret_aws_secret_access_key: ${secret:aws.secret_access_key}
sample.dig
+task1:
  !include : sub/secrets.dig
  sh>: echo ${secret_gcp_credential}
+task2:
  !include : sub/secrets.dig
  sh>: echo ${secret_gcp_credential}
+task3:
  !include : sub/secrets.dig
  sh>: echo ${secret_gcp_credential}

それでも全タスクに書かないとダメ。

Python API で digdag.env.store に入れる

Python (または Ruby) API で digdag.env.store に入れると楽できそう。

以下のような Digdag の Python API を使ったスクリプトをどこか tasks ディレクトリにでもおいておく。

secret_ で始まる os.environ な環境変数をdigdag.env.store で設定するスクリプト。

tasks/__init__.py
import digdag
import os

class Enviroment(object):
    def set_secret_env(self):
        params = {}
        for k, v in os.environ.items():
            if k.startswith("secret_"):
                params[k] = v
        digdag.env.store(params)

digdag.env.store で設定されたパラメータは以降のタスクでも環境変数として読み込めるようになる性質があるので、このスクリプトを先頭のタスクで呼び出せばよい。

.dig ファイルは次のようになる。つまり _env を一度だけ書けば済むようになる。

sample.dig
+prepare_environment:
  _env:
    secret_gcp_credential: ${secret:gcp.credential}
    secret_aws_access_key_id: ${secret:aws.access_key_id}
    secret_aws_secret_access_key: ${secret:aws.secret_access_key}
  py>: tasks.Enviroment.set_secret_env
+task2:
  sh>: echo ${secret_gcp_credential}
+task3:
  sh>: echo ${secret_gcp_credential}

これで良いのでは、と最初は思ったのだが、digdag.env.store を使うと digdag server を使っている場合に Web UI の Store Params カラムに設定した secrets が表示されてしまうことに気づいた。server モードでは正直使いにくい。

結論

digdag server を使うつもりなので、面倒だが !include するしかないか、という気持ちになっている。

なにか良いソリューションがあったら教えてください。

将来への期待

digdag.env.store しても Web UI に表示しないモードがあると嬉しい。Issue digdag#968

さらに Python API で ${secret:gcp.credential} のような secrets に直接アクセスできると、_env を1つも書かずに機械的にマップできるようになると思うのだが、現状ではそれもできないので Issue digdag#942 だけ上げてある。

あとはトップレベルの _export で secrets を環境変数にマッピングができると Python スクリプトを用意せずに済むので対応して欲しい。digdag#926