bootstrapの設定にAPIトークンを埋め込みたいがmise.tomlには書きたくない

【mise】mise bootstrap filesでシステムファイルを宣言的に配置する のようなbootstrap設定で、配置するファイルにAPIトークンやパスワードを含めたい場合がある。[bootstrap.secrets]は、こうした機密情報の「入力」を宣言するためのセクションで、値そのものはmise.tomlに書かず、環境変数から供給する。mise bootstrap secretsは、宣言した入力が実際に利用可能かどうかを、値を表示せずに確認するコマンドである。

[bootstrap.secrets]でシークレット入力を宣言する

論理名と環境変数名を1行で対応付ける短縮形と、descriptionallow_emptyを追加できるテーブル形式がある。

[bootstrap.secrets]
cache_token = "MISE_CACHE_TOKEN"

[bootstrap.secrets.database_password]
env = "PRODUCTION_DATABASE_PASSWORD"
description = "Production database password"

mise bootstrap secrets statusで有無を確認する

環境変数を設定していない状態ではmissingと表示される。

$ mise bootstrap secrets status
cache_token        MISE_CACHE_TOKEN              missing
database_password  PRODUCTION_DATABASE_PASSWORD  missing

環境変数を設定するとavailableになる。値そのものはどの状態でも一切表示されない。

$ MISE_CACHE_TOKEN=supersecret123 PRODUCTION_DATABASE_PASSWORD=hunter2 mise bootstrap secrets status
cache_token        MISE_CACHE_TOKEN              available
database_password  PRODUCTION_DATABASE_PASSWORD  available

環境変数が空文字列の場合はemptyになる。デフォルトでは空文字列は許可されない。

$ MISE_CACHE_TOKEN='' mise bootstrap secrets status
cache_token        MISE_CACHE_TOKEN              empty

–missingと–jsonでスクリプトから扱う

--missingを付けると、いずれかの入力が利用できない場合に終了コード1を返す。CIやスクリプトから、bootstrapを実行する前の事前チェックに使える。

$ mise bootstrap secrets status --missing
$ echo $?
1

--jsonを付けると構造化された出力を得られる。

$ MISE_CACHE_TOKEN=supersecret123 mise bootstrap secrets status --json
[
  {
    "name": "cache_token",
    "env": "MISE_CACHE_TOKEN",
    "state": "available"
  },
  {
    "name": "database_password",
    "env": "PRODUCTION_DATABASE_PASSWORD",
    "state": "missing",
    "description": "Production database password"
  }
]

allow_empty = trueで空文字列を許容する

allow_empty = trueを付けると、空文字列でもavailableとして扱われる。未設定(環境変数が存在しない)の場合はallow_emptyを付けてもmissingのままである。

[bootstrap.secrets.optional_token]
env = "OPTIONAL_TOKEN"
allow_empty = true
$ mise bootstrap secrets status
optional_token  OPTIONAL_TOKEN  missing

$ OPTIONAL_TOKEN='' mise bootstrap secrets status
optional_token  OPTIONAL_TOKEN  available

secret()で参照するにはtemplate = trueが必要

宣言したシークレットを実際にファイルの中身へ埋め込むには、{{ secret(name="...") }}というテンプレート構文を使う。ただし[bootstrap.files]側でtemplate = trueを明示しないと、content{{ }}はテンプレートとして解釈されず、文字列としてそのままファイルに書き込まれてしまう。

[bootstrap.secrets.api_token]
env = "API_TOKEN"

[bootstrap.files."/etc/myapp/token"]
content = "token={{ secret(name=\"api_token\") }}\n"
template = true
mode = "0600"

API_TOKENを設定せずに適用しようとすると、ファイルを書き込む前でエラーとなる。

$ mise bootstrap files apply -y
mise ERROR [bootstrap.files]."/etc/myapp/token": failed to render template
mise ERROR required bootstrap secrets are unavailable: api_token (API_TOKEN). Supply them in the environment (for example, `fnox exec -- mise bootstrap ...`) or pass --prompt-secrets

API_TOKENを設定してから実行すると、実際の値がファイルに書き込まれる。

$ API_TOKEN=abc123xyz mise bootstrap files apply -y
mise system files: applied 1 change(s)

$ cat /etc/myapp/token
token=abc123xyz

template = trueの付け忘れは、シークレット未設定でもエラーにならないため気づきにくい。secret()を使う[bootstrap.files]エントリでは、template = trueの有無を必ず確認する。