tech.guitarrapc.cóm

Technical updates

Pulumi の設定を Config で保持する

この記事は、Pulumi dotnet Advent Calendar 2019 の10日目です。

qiita.com

Pulumi は Web UIがあり、そこにはConfig が見えます。 実際にコードでも Config が参照でき、機密情報はConfigに保持して参照することでgit から分離できてよさそうです。 早速見てみましょう。

目次

TL;DR

  • Pulumi は、Config設定をProjectに紐づけて保持できる。
  • Config 値はローカルの pulumi.STACK.yaml にも保持される。
  • Secretはログインしているユーザーでないと復号できないようになっている。
  • 構造化コンフィグがサポートされたのでJSONではこっちを使うとよい

イメージ的には、terraform.tfvars がStackに紐づけて保持され、WebUI や CLI、プログラムアクセスで担保された感じ。

基本的な想定環境

Pulumi CLI の動作は公式ドキュメントを頼りに見ていくことになる。 この公式ドキュメントの記載は動作環境に Bash のような Unix Shell (原文ママ) を想定している。

Most of our command line snippets in the docs are for a Unix shell like bash https://github.com/pulumi/docs/issues/2062#issuecomment-560501274

そのため、Windows 環境のコマンドプロンプトや PowerShell ではコマンドがそのまま動かないことがあるので注意されたい。

CLIでのConfig操作

Pulumi config は、 CLI でサクッと設定、取得ができる。

  • pulumi config コマンドに、setget サブコマンドを組み合わせて、key-value ペアを管理していく。

基本的なコマンドは次の通り

  • pulumi config set <key> [value] : key に value の値を保持する
  • pulumi config get <key>: key の値を取得する
  • pulumi config: コンフィグ全部取得。--json でJSON として取得

Key は、[namespace:]key-name という組み合わせで構成されている。namespace は任意で省略して key-name のみも可能。namespace を省略した場合、Pulumiが自動的に現在のプロジェクト名を pulumi.yaml から取得して差し込んでくる。

簡単なkey-value 操作を見てみる。現在のプロジェクトで使うconfig値を設定するなら、シンプルに namespace なしにキーを設定できる。

# foo というキーに bar という値を設定
$ pulumi config set foo bar
$ pulumi config get foo
bar

あるいは aws パッケージで使うaws 環境のリージョンを仕込むときは、 aws: namespace を付けて次のように定義する。

$ pulumi config set aws:region ap-northeast-1
$ pulumi config get aws:region
ap-northeast-1

標準入力を value として受け取ることもできる。(この例は Bash/PowerShell/CMD すべてで同じだが、コマンドによってはパイプラインの違いで結果が変わってくるので注意)

$ echo fuga | pulumi config set hoge
$ pulumi config get hoge

秘密文字は、--secret フラグを付ける。--secret はただ base64をした値ではなく、Stackごとの暗号鍵+VaultごとのSalt で暗号化する。 中を見ようとしても、config一覧では [secret] とマスクされている。 直接keyにアクセスすると値が取れる。

$ pulumi config set --secret dbPassword S3cr37
$ pulumi config
KEY                     VALUE
dbPassword              [secret]
$ pulumi config get dbPassword
S3cr37

秘密文字は、awskms など任意の鍵を使うこともできるので必要なら使ってもいい。

Initializing a Stack with Alternative Encryption - Configuration and Secrets

プログラムでのConfig操作

任意のプログラミング言語でPulumi config を取得できるようにAPIが用意されている。C#で Config操作するときはAPIがいくつか生えているので使い分ける必要がある。

まずは new Config でインスタンスを取得したら、ここからConfigにアクセスできる。

var config = new Pulumi.Config();

// foo はオプショナルに取得。なくてもエラーは出ない。
var optionalFoo = config.Get("foo");

// foo はあるものとして取得。なかったらthrow。
var config.Require("foo");

// Secretの取得。実行時はプレーンテキストになるので取扱いに注意
var config.RequireSecret("dbPassword");

Getは型ごとにも用意されているので、適当に使うといい。

f:id:guitarrapc_tech:20191209020051p:plain

動きの把握はコード見たほうが早い。

https://github.com/pulumi/pulumi/blob/eec14527b17584e9a09b786514d9ae164bdeae61/sdk/dotnet/Pulumi/Config.cs#L63

Secret は実行時に生の値になっているので注意、かつ型的には Output<T> となる。

Web UI での確認

Stack ごとに Config は紐づけて保持される。

Web UI でもConfigは確認できる。 Stack を開くとすぐに表示されている。

f:id:guitarrapc_tech:20191209020102p:plain

また Activity でも一件ごとにConfigを確認できる。

f:id:guitarrapc_tech:20191209020121p:plain

ローカルでの Config値

値を設定すると、ローカルの Pulumi.Stack名.yaml にも保持される。

Secret の場合、暗号化された状態で保持されている。

config:
  foo: bar
  aws-sandbox:dbPassword:
    secure: AAABADU0Y5WFz8kp4BGIsqACA+NTPvKBOA1VQQzartD+QBVyesk=

暗号化されているので、git にコミット自体は可能

構造化されたConfig

前はJSON で保持みたいな記述でしたが、新しくYAML方式な構造が提供された。

# JSON で構造化データの投入
$ pulumi config set data '{"active": true, "nums": [1,2,3]}'

# 新しい構造化方式でデータを投入
$ pulumi config set --path data.active true
$ pulumi config set --path data.nums[0] 1
$ pulumi config set --path data.nums[1] 2
$ pulumi config set --path data.nums[2] 3

最近のCLI でよくある、terraform でもよく見るやり方なので、標準的に使えるのはうれしいところ。

JSONでは投入時に、CMD/PowerShell でエスケープの追加対応が必要だったが、構造化データではその考慮は不要でどのシェルでもほぼ同じコマンドで動く。

Escape for `pulumi config set` on Windows CMD and PowerShell · Issue #2062 · pulumi/docs

構造化データを投入すると、 Pulumi.Stack名.yaml は次のようなYAML構造で保持されます。

config:
  aws-sandbox:data:
    active: true
    nums:
    - 1
    - 2
    - 3

C#的には、 System.Text.Json を使って構造化データにアクセスします。

GetProperty() 時点ではJsonEelementなので、GetBoolean() などで型を明示しないと使いにくいので注意。

var config = new Pulumi.Config();
var data = config.RequireObject<JsonElement>("data");
var active = data.GetProperty("active").GetBoolean();
Console.WriteLine($"Active: {active}");

直近のデプロイ時のConfig にローカルのConfigを更新する

pulumi config refresh を行うと、現在の Pulumi.Stack名.yaml がバックアップされ、直近のデプロイ (pulumi up` 時のconfig を持ってきます。

あまり使わないけど、知っておくと便利なのでオススメ。

REF

公式ドキュメントに沿ってるのでみてみるのおすすめ。

Configuration and Secrets - Pulumi