最近 Vault クラスターの作成と Nomad と Vault の統合を行いました。

Vault を HA モードで使う
このブログの SSL/TLS 証明書を Vault [https://www.vaultproject.io/] で管理しようと考えています。 * Let’s Encrypt のクライアントを Nomad ジョブとして実行し SSL 証明書を取得してみた [https://blog.lorentzca.me/run-letsencrypt-client-with-nomad-job/] 現在サーバーは 3 台でクラスターを組んでおり、 Nomad [https://www.nomadproject.io/…
Nomad と Vault を統合する
現在 Nomad [https://www.nomadproject.io/] と Consul [https://www.consul.io/] を使用してこのブログを動かしています。 * nomad - ゆるふわキャンパー [https://blog.lorentzca.me/tag/nomad/] * consul - ゆるふわキャンパー [https://blog.lorentzca.me/tag/consul/…

今回は Nomad タスクから Vault にアクセスし、データの書き込み/読み込みを試してみます。

vault スタンザ

Nomad ジョブでは Vault のトークンを取得し、VAULT_TOKEN 環境変数へ登録する vault スタンザがあります。vault スタンザは job, group, task の各スタンザで定義できます。

vault スタンザでは以下のようにポリシーを指定することでそのポリシーの権限を持つトークンが発行されます。

vault {
  policies = ["nomad-client"]
}

発行されたトークンは VAULT_TOKEN 環境変数に自動でセットされます。

vault スタンザを使ったジョブの例

Vault の KVS へデータを登録するタスク、データを取得するタスクを作成してみます。なお、データを登録する前に取得が行われると困るので最近追加された lifecycle スタンザ を使用しデータ取得タスクの前にデータ登録タスクが実行されるようにしています。

job "testjob" {
  datacenters = ["vagrant"]

  type = "batch"

  group "testgroup" { 
    vault {
      policies    = ["nomad-client"]
      change_mode = "restart"
    }

    task "write-vault" {
      driver = "exec"
      lifecycle {
        hook    = "prestart"
      }
      env {
        VAULT_ADDR = "http://127.0.0.1:8200"
      }
      config {
        command = "/usr/local/bin/vault"
        args = ["kv", "put", "secret/hello", "nomad=hello-${VAULT_TOKEN}"]
      }
      resources {
        memory = 10
      }
    }

    task "read-vault" {
      driver = "exec"
      env {
        VAULT_ADDR = "http://127.0.0.1:8200"
      }
      config {
        command = "/usr/local/bin/vault"
        args = ["kv", "get", "secret/hello"]
      }
      resources {
        memory = 10
      }
    }
  }
}

ジョブの実行

上のジョブを実行するためには secrets/ kv を有効にし、 Nomad ジョブに secrets/ kv へのアクセス許可を与えるポリシーを作成しておく必要があります。

$ vault secrets enable -path=secret/ kv

$ cat nomad-client-policy.hcl
path "secret/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
$ vault policy write nomad-client nomad-client-policy.hcl

準備が終わったらジョブを実行します。

$ nomad job run testjob.hcl

ログを確認し、 Vault へのデータの書き込み、読み込みが成功していることを確認できました!🎉
トークンが取得できていることも確認できてます。

$ nomad alloc logs ab5c3588 write-vault
Success! Data written to: secret/hello

$ nomad alloc logs ab5c3588 read-vault
==== Data ====
Key      Value
---      -----
nomad    hello-s.1luWkd2dWvM5KeLKM46FF7zj

なお、vault スタンザで change_mode = "restart" と指定しているので、以下の通りジョブを停止後はトークンが破棄されています。安全!バッチジョブと相性バッチリですね。バッチだけに。😊

$ vault token lookup s.1luWkd2dWvM5KeLKM46FF7zj
Error looking up token: Error making API request.

URL: POST http://127.0.0.1:8200/v1/auth/token/lookup
Code: 403. Errors:

* bad token

感想

Vault と Nomad をセットアップする部分は慣れていないとちょっと大変でしたが、一度連携ができれば簡単に使えますね!

これで機密情報を良い感じに管理できるようになりました!✨

参考