序章

Vault は、APIキー、アクセストークン、パスワードなどのシークレットを保存および配布するための安全で信頼性の高い方法を提供するオープンソースツールです。 Vaultのようなソフトウェアは、シークレットや機密データの使用を必要とするアプリケーションを展開するときに非常に重要になる可能性があります。

このチュートリアルでは、次のことを行います。

  • Vaultをインストールし、システムサービスとして構成します
  • 暗号化されたオンディスクデータストアを初期化します
  • TLSを介して機密値を安全に保存および取得する

いくつかの追加ポリシーを設定すると、Vaultを使用して、さまざまなアプリケーションやツールの機密データを安全に管理できるようになります。

機密情報を管理する他のサービスと同様に、本番環境のような環境で使用する前に、Vaultの導入のベストプラクティスに関する追加のドキュメントを読むことを検討する必要があります。 たとえば、 Vaultの本番強化ガイドは、ポリシー、ルートトークン、監査などのトピックをカバーしています。

前提条件

このガイドを開始する前に、次のものが必要です。

  • Ubuntu 20.04の初期セットアップガイドに従ってセットアップされた1つのUbuntu20.04サーバー(sudo非rootユーザーとファイアウォールを含む)。
  • VaultのHTTPAPIを保護するために使用するTLS証明書。 Ubuntu20.04用のこのCertbotスタンドアロンモードチュートリアルに従って無料で入手できます。

:パッケージを初めてインストールすると、Vaultは自己署名TLS証明書を生成します。 Vaultで使用するドメイン名またはTLS証明書がないが、このチュートリアルの手順を実行したい場合は、このチュートリアルのコマンドに-tls-skip-verifyフラグを追加するか、次の方法でTLS検証をスキップできます。 VAULT_SKIP_VERIFY環境変数を定義します。

このオプションは、Vaultの実験にのみ適しており、実稼働環境では使用しないでください。

ステップ1—Vaultをインストールする

HashiCorpはVaultを典型的なDebian/Ubuntuパッケージとして提供しているため、サーバーのパッケージソースのリストにパッケージリポジトリを追加する通常の手順を実行します。

まず、Hashicorpの GPGキーをパッケージマネージャーに追加して、システムがパッケージリポジトリを信頼するようにします。

  1. curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

次に、リポジトリ自体をパッケージソースのリストに追加して、定期的な更新がチェックされるようにします。

  1. sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

次に、パッケージをインストールします。

  1. sudo apt install vault

これで、vaultコマンドを使用できます。 Vaultのバージョンをチェックして、動作することを確認してください。

  1. vault --version
Output
Vault v1.8.5 (647eccfe0bd5817bdd8628f3c3171402dfc8a8fc)

Vault実行可能ファイルはサーバーにインストールされているため、次のステップは、システムサービスとして実行するようにVault実行可能ファイルを構成することです。

ステップ2—Vaultを構成する

Vaultパッケージをインストールすると、システムにvault vault ユーザーが自動的に作成され、Vaultをバックグラウンドで実行するためのシステムサービスがセットアップされます。 Let’s Encryptによって生成されたHTTPS証明書を使用するには、デフォルトの構成にいくつかの変更を加える必要があります。

:このチュートリアルでは、デフォルトで、Vaultはファイルシステムバックエンドを使用して、暗号化されたシークレットを/opt/vaultのローカルファイルシステムに保存します。 これは、複製する必要のないローカルまたは単一サーバーのデプロイメントに適しています。 Consulバックエンドなどの他のVaultバックエンドは、暗号化されたシークレットを分散キー/値ストア内に保存します。

Vaultのデフォルト設定は/etc/vault.d/vault.hclに保存されます。 このファイルを使用して、暗号化されたシークレットが保存されている場所など、Vaultのさまざまなオプションを制御します。

nanoまたはお好みのテキストエディタを使用してvault.hclを開きます。

  1. sudo nano /etc/vault.d/vault.hcl

このブロックを含むファイルのlistener "tcp"セクションを見つけます。 nanoを使用している場合は、Ctrl+Wを押してから、listener “tcp”と入力して、その行を直接検索できます。

/etc/vault.hcl
listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/tls.crt"
  tls_key_file  = "/opt/vault/tls/tls.key"
...
}

tls_cert_file行とtls_key_file行を編集して、Let’sEncryptの証明書とキーファイルを指すようにします。 各行の強調表示されたyour_domain部分の代わりに、独自のドメイン名に置き換えることを忘れないでください。

/etc/vault.hcl
listener "tcp" {
...
  tls_cert_file = "/etc/letsencrypt/live/your_domain/fullchain.pem"
  tls_key_file = "/etc/letsencrypt/live/your_domain/privkey.pem"
}

:このサーバーへの外部接続を今のところ防ぐために、address = "0.0.0.0:8200"address = “127.0.0.1:8200”に変更する必要があります。 127.0.0.1は、ローカルホスト専用の予約済みアドレスです。 これは、サービスが適切に保護される前に、サービスがパブリックインターネットに公開されないようにするためです。 これは後で更新できますが、今のところ、この構成変更により、vaultコマンドを使用して、HTTPSで保護されたドメイン名を正しく解決できるようになります。

ファイルを保存して閉じます。 nanoを使用している場合は、Ctrl+Xを押し、ファイルの保存を求めるメッセージが表示されたらYを押し、Enterを押して確認します。

次に、vaultシステムユーザーにも、これらの証明書を読み取るためのアクセス許可が必要です。 デフォルトでは、これらの証明書と秘密鍵にはrootからのみアクセスできます。 これらを安全に利用できるようにするために、これらのファイルにアクセスするためのpkiという特別なグループを作成します。 グループを作成し、vaultユーザーを追加します。

  1. sudo groupadd pki

/etc/letsencryptディレクトリ内の2つのディレクトリのアクセス許可を更新して、pkiグループのメンバーがコンテンツを読み取れるようにします。

  1. sudo chgrp -R pki /etc/letsencrypt/archive
  2. sudo chgrp -R pki /etc/letsencrypt/live
  3. sudo chmod -R g+rx /etc/letsencrypt/archive
  4. sudo chmod -R g+rx /etc/letsencrypt/live

次に、vaultユーザーをpkiグループに追加します。 これにより、Vaultが証明書にアクセスできるようになり、HTTPSを介して安全にリクエストを処理できるようになります。

  1. sudo usermod -a -G pki vault

便宜上の最後のステップとして、/etc/hostsにルールを追加して、Vaultへのリクエストをlocalhostに送信します。

次のコマンドのyour_domainを、Let’sEncrypt証明書を取得したドメインに置き換えます。

  1. echo 127.0.0.1 your_domain.com | sudo tee -a /etc/hosts

このコマンドは、127.0.0.1 your_domain.com行を/etc/hostsに追加して、Vaultサーバーでyour_domain.comに対して行うHTTP要求はDNSを無視し、localhostに直接送信されるようにします。 。

Vaultサービスがセットアップされ、Vault構成ファイルが完成したら、Vaultを起動してシークレットストアを初期化する準備が整いました。

ステップ3—Vaultを初期化する

Vaultを最初に起動すると、初期化されません。つまり、データを受信して保存する準備ができていません。 チュートリアルのこのセクションでは、Vaultサーバーを起動し、Vaultのシークレットストアを開封(開く)するために使用される一連のシークレットキーを使用してサーバーを初期化します。

Vaultを初めて起動すると、暗号化されたシークレットを実際に保存するバックエンドも初期化されません。 Vaultシステムサービスを開始してバックエンドを初期化し、Vault自体の実行を開始します。

  1. sudo systemctl start vault.service

クイックチェックを実行して、サービスが正常に開始されたことを確認できます。

  1. sudo systemctl status vault.service

次のような出力が表示されます。

Output
● vault.service - "HashiCorp Vault - A tool for managing secrets" Loaded: loaded (/lib/systemd/system/vault.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2021-11-16 21:55:13 UTC; 22s ago Docs: https://www.vaultproject.io/docs/ Main PID: 104207 (vault) Tasks: 7 (limit: 1137) Memory: 179.3M CGroup: /system.slice/vault.service └─104207 /usr/bin/vault server -config=/etc/vault.d/vault.hcl

そのコマンドの出力には、プロセスIDやリソースの使用状況など、実行中のサービスに関するいくつかの情報が含まれている必要があります。 次の行が出力に含まれていることを確認してください。これは、サービスが正しく実行されていることを示しています。

Output
. . . Active: active (running) . . .

サービスがアクティブでない場合は、コマンドの出力の最後にある付随するログ行を調べて、Vaultの出力を確認してください。これは、問題を特定するのに役立ちます。

次に、vaultコマンドにVaultサーバーへの接続方法を指示する環境変数を設定します。 ステップ1で、ローカルループバックインターフェイスでのみリッスンするようにVaultを構成したため、VAULT_ADDR環境変数をローカルHTTPSエンドポイントに設定します。

  1. export VAULT_ADDR=https://your_domain:8200

vaultコマンドがデーモンと通信できるようになりました。 HTTPS証明書を適切に検証するには、単にlocalhostまたは127.0.0.1ではなく実際のホスト名を定義する必要があることに注意してください。

ボールトサーバーのステータスを確認して、ボールトサーバーが初期化されていない状態になっていることを確認します。

  1. vault status

サーバーは、機能しているがまだ初期化されていないことがわかるように、出力を返す必要があります。

Key Value
--- -----
Seal Type shamir
Initialized false
Sealed true
Total Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version 1.8.5
Storage Type file
HA Enabled false

Vaultが初期化時に公開する情報は2つあり、他の時点では利用できません

  • 初期ルートトークン。 これは、Vault展開に対するルート権限に相当し、すべてのVaultポリシー、マウント、およびシークレットの管理を可能にします。
  • キーを開封します。 これらは、デーモンの起動時にVaultのシールを解除するために使用されます。これにより、Vaultデーモンがバックエンドシークレットストアを復号化できるようになります。

より具体的には、Vaultの開封プロセスは、キー共有によって形成されたキーを使用してバックエンドを復号化します。 Vaultを最初に初期化するときに、作成するアンシールキーの数と、Vaultを正常にアンシールするためにアンシール時に必要な数を選択できます。 Vaultのシーリングメカニズムの詳細については、Vaultのドキュメントを参照してください。

アンシールパラメータの一般的な構成は、3つのキーを作成し、アンシール時にそれらのキーのうち少なくとも2つを必要とすることです。 これにより、重要なキー共有を分離して別々の場所に保存し、侵害したキー共有がVaultの開封に十分でないことを確認できます。

つまり、Vaultを起動するたびに、サービスを使用可能にして使用できるようにするために、少なくとも2つの開封キーが必要になります。 封印されている間、実際の秘密の値を保存するファイルは暗号化されたままになり、アクセスできなくなります。

-key-shares=3オプションを使用して3つの開封キーでボールトを初期化し、-key-threshold=2フラグでボールトを開封するには少なくとも2つのキーが必要です::

  1. vault operator init -key-shares=3 -key-threshold=2

次のような出力が表示されます。

Output
Unseal Key 1: eZcJeydRrqeSMZ1zTN+VVll9TFT2KvJy7VlnxUgtvuz5 Unseal Key 2: ntmqCKq8rgNnKT1YSLCjVmCCZBAA3NwUeqxIyRpYD4Wm Unseal Key 3: 3FK1+Hsorh4p8/L9mki3VskaEU2eQhLqGOI/pJkTHMbx Initial Root Token: s.hY0ieybfDqCadz7JpL88uO3x

必ず各開封トークンと最初のルートトークンを安全な方法で保存してください。 これらのキーとルートトークンを再度取得することはできなくなります。 たとえば、1つのオプションは、1つの開封キーをパスワードマネージャーに保存し、別のキーをUSBドライブに保存し、別のキーをGPG暗号化ファイルに保存することです。

vault statusをもう一度調べると、Initializedステータスがtrueに設定され、Total SharesThresholdの値にボールトを開封するために必要なキーシャードの数とキーの最小数。

  1. vault status
Output
. . . Initialized true Sealed true Total Shares 3 Threshold 2 Unseal Progress 0/2 . . .

Unseal Progess行に値0/2が表示されていることに注意してください。 新しく作成した開封トークンを使用して、Vaultの開封を開始します。 vault operator unsealコマンドを実行し、プロンプトが表示されたら任意のキーを入力します。

  1. vault operator unseal

コマンドは、開封トークンを要求します。

Output
Key (will be hidden):

入力後、コマンドからの出力は、開封が進行中であることを示しますが、Vaultを使用する準備ができるまでにもう1つの開封キーが必要です。

Output
Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 3 Threshold 2 Unseal Progress 1/2 Unseal Nonce 0f3a328b-e0c6-6294-d6a2-56da49271dff Version 1.8.5 Storage Type file HA Enabled false

Unseal Progress 1/2行が出力でどのように変化したかに注目してください。 unsealコマンドを再実行してください。

  1. vault operator unseal

そして、すでに使用したものとは異なるキーを入力します。

Output
Key (will be hidden):

コマンドの出力は、開封プロセスが正常に完了したことを示しています。

Output
Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 3 Threshold 2 Version 1.8.5 Storage Type file Cluster Name vault-cluster-3042c7bc Cluster ID c3e9d814-cf2a-2901-f0e4-ebc52d29e5cc HA Enabled false

これでVaultは開封され、使用できるようになりました。 これらの開封手順は、Vaultを起動または再起動するたびに必要です。

ただし、開封は、トークンによって認証されるVaultとの通常の相互作用(値の読み取りや書き込みなど)とは異なるプロセスです。 次の手順では、シークレット値を格納し、Vaultの特定のパスに対して読み取り/書き込みを行うために必要なアクセストークンとポリシーを作成します。

ステップ4—秘密の読み取りと書き込み

Vaultで使用できるシークレットバックエンドはいくつかありますが、この例では、kvシークレットバックエンドを使用します。 このバックエンドは、単純なキーと値のペアをVaultに格納します。 ただし、デフォルトでは有効になっていません。

チュートリアルのこのセクションでは、kvシークレットバックエンドを有効にしてから、シークレットの読み取りと書き込みの方法を学習します。

まず、使いやすさのために、以前に生成されたルートトークンをシェル変数に保存します。

  1. root_token=your_root_token_here

次に、ルートトークンで認証しているときに、kvバックエンドを有効にします。

  1. VAULT_TOKEN=$root_token vault secrets enable kv

コマンドが成功すると、次のような出力が表示されます。

Output
Success! Enabled the kv secrets engine at: kv/

次に、それが利用可能なシークレットバックエンドのローカルリストに追加されていることを確認できます。

  1. VAULT_TOKEN=$root_token vault secrets list

次のような出力を受け取るはずです。

Output
Path Type Accessor Description ---- ---- -------- ----------- cubbyhole/ cubbyhole cubbyhole_abc1631b per-token private secret storage identity/ identity identity_631fe262 identity store kv/ kv kv_4d5855c8 n/a sys/ system system_79b13f2f system endpoints used for control, policy and debugging

新しいkvバックエンドが有効になっていることを示す強調表示された行に注意してください。 これで、このバックエンドを使用していくつかのデータを保存できます。

  1. VAULT_TOKEN=$root_token vault write kv/message value=mypassword

このコマンドでは、強調表示されたkv/プレフィックスは、kvパスにマウントされたkvバックエンドに書き込み、キーvalueを格納していることを示します。パスmessageで、値はmypasswordです。 スーパーユーザー権限を持つルートトークンを使用して、一般的なシークレットを記述しました。

vault readコマンドを使用して作成したシークレットを確認してください。

  1. VAULT_TOKEN=$root_token vault read kv/message

作成したシークレットの内容とともに、次のような出力を受け取るはずです。

Output
Key Value --- ----- refresh_interval 768h value mypassword

ただし、ルートトークンのみを使用してVaultを作成、読み取り、またはその他の方法で操作することは、安全ではなく、チーム設定でスケーラブルであり、シークレットへのきめ細かいアクセス制御を許可しません。 次のセクションでは、ポリシーを定義し、追加のアクセストークンを作成して、ユーザーがVaultを操作する方法を制限する方法を学習します。

ステップ5—承認ポリシーを作成する

実際のシナリオでは、外部ツールが使用できるAPIキーやパスワードなどの値を保存できます。 ルートトークンを使用してシークレット値を再度読み取ることもできますが、単一のシークレットに対する読み取り専用のアクセス許可を持つ特権の低いトークンを生成することを示しています。

チュートリアルのこのセクションでは、シークレットへの読み取り専用アクセスを強制するVaultポリシーを作成します。 ポリシーを作成するには、ファイルを編集してから、vault policyコマンドを使用してVaultにロードする必要があります。

ポリシーの作成を開始するには、nanoまたはお好みのエディターを使用して、policy.hclというファイルを開きます。

  1. nano policy.hcl

シークレットパスへの読み取り専用アクセスを定義する次のVaultポリシーをファイルに入力します。

policy.hcl
path "kv/message" {
     capabilities = ["read"]
}

ファイルを保存して閉じてから、このポリシーをVaultに書き込みます。 次のコマンドは、policy.hclファイルをVaultにロードし、読み取り専用機能を備えたmessage-readonlyという名前のポリシーを作成します。

  1. VAULT_TOKEN=$root_token vault policy write message-readonly policy.hcl

次に、Vaultへの読み取り専用アクセスに使用するトークンを作成します。 -policy=”message-readonly”フラグをvault token createコマンドに追加して、作成した新しいポリシーを使用します。

  1. VAULT_TOKEN=$root_token vault token create -policy="message-readonly"

出力は次のようになります。

Output
Key Value --- ----- token your_token_value token_accessor your_token_accessor token_duration 768h0m0s token_renewable true token_policies ["default" "message-readonly"] identity_policies [] policies ["default" "message-readonly"]

強調表示されたyour_token_value値をapp_tokenという環境変数に保存します。

  1. app_token=your_token_value

app_tokenの値を使用して、パスkv/messageに格納されているデータにアクセスできます(Vaultには他の値はありません)。

  1. VAULT_TOKEN=$app_token vault read kv/message
Output
Key Value --- ----- refresh_interval 768h0m0s value mypassword

この非特権トークンが、Vaultにシークレットを一覧表示するなど、他の操作を実行できないことをテストすることもできます。

  1. VAULT_TOKEN=$app_token vault list kv/
Output
Error reading kv/: Error making API request. URL: GET https://your_domain:8200/v1/secret?list=true Code: 403. Errors: * 1 error occurred: * permission denied

これにより、特権の低いアプリトークンが、Vaultポリシーで明示的に指定されているもの以外の破壊的なアクションを実行したり、他の秘密の値にアクセスしたりできないことが確認されます。 読み取り専用トークンを引き続き使用する場合は、将来使用できるように安全な場所に記録してください。

結論

この記事では、Ubuntu 20.04にVaultをインストール、構成、およびデプロイしました。 また、Vaultを開封するためのシャードキーを作成し、kvバックエンドシークレットストアを有効にし、ユーザーがVaultシークレットを操作する方法を制限する読み取り専用ポリシーを定義しました。

このチュートリアルでは、非特権トークンの使用方法のみを示しましたが、Vaultのドキュメントには、シークレットを保存およびアクセスするための追加の方法代替認証方法の例がさらにあります。

これらの手順は、Vaultのコア機能のいくつかを展開して使用する方法を示しています。 ニーズによっては、他の構成変更やより複雑なポリシーが必要になる場合があります。 必ずVaultのドキュメントを読み、必要に応じて適切な構成変更を行ってください。 本番環境に対応した変更には、次のものが含まれる場合があります。

  • 日常的に使用するための特権の低いトークンを生成します。 これらのトークンが使用する必要のある特定のポリシーは、特定のユースケースによって異なりますが、このチュートリアルの例app_tokenは、制限付き特権のトークンとポリシーを作成する方法を示しています。

  • チームが使用するサービスの一部としてVaultを展開する場合は、各チームメンバーの封印解除キーを使用してVaultを初期化します。 このアプローチにより、Vaultのストレージは、複数のチームメンバーがプロセスに参加している場合にのみ復号化されます。