Ubuntu16.04でHashiCorpVaultを使用してシークレットを安全に管理する方法
序章
Vault は、APIキー、アクセストークン、パスワードなどのシークレットを保存および配布するための安全で信頼性の高い方法を提供するオープンソースツールです。 Vaultのようなソフトウェアは、シークレットや機密データの使用を必要とするアプリケーションを展開するときに非常に重要になる可能性があります。
このチュートリアルでは、次のことを行います。
- Vaultをインストールし、システムサービスとして構成します
- 暗号化されたオンディスクデータストアを初期化します
- TLSを介して機密値を安全に保存および取得する
いくつかの追加ポリシーを設定すると、Vaultを使用して、さまざまなアプリケーションやツールの機密データを安全に管理できるようになります。
機密情報を管理する他のサービスと同様に、本番環境のような環境で使用する前に、Vaultの導入のベストプラクティスに関する追加のドキュメントを読むことを検討する必要があります。 たとえば、 Vaultの本番強化ガイドは、ポリシー、ルートトークン、監査などのトピックをカバーしています。
前提条件
このガイドを開始する前に、次のものが必要です。
- Ubuntu 16.04の初期セットアップガイドに従ってセットアップされた1つのUbuntu16.04サーバー(sudo非rootユーザーとファイアウォールを含む)。
- VaultのHTTPAPIを保護するために使用するSSL証明書。 このCertbotスタンドアロンモードチュートリアルに従って、無料で入手できます。
ステップ1—Vaultをインストールする
HashiCorpはVaultを単一のバイナリとして提供するため、Vaultの実行可能ファイルを手動でダウンロードしてインストールします。
まず、64ビットLinux用の圧縮されたVaultzipアーカイブをダウンロードします。 最新バージョン(執筆時点では0.9.5)へのリンクは、Vaultのダウンロードページにあります。
- wget https://releases.hashicorp.com/vault/0.9.5/vault_0.9.5_linux_amd64.zip
次に、このファイルのチェックサムをダウンロードして、ダウンロードを確認できるようにします。
- wget https://releases.hashicorp.com/vault/0.9.5/vault_0.9.5_SHA256SUMS
次に、zipアーカイブの整合性を確認します。 これは、zipアーカイブの内容がHashicorpがVaultのバージョン0.9.5でリリースしたものと一致することを確認するためです。
- grep linux_amd64 vault_*_SHA256SUMS | sha256sum -c -
SHA256SUMS
ファイルの各行には、HashiCorpが提供するzipアーカイブごとに1つずつ、チェックサムとファイル名があります。 上記のコマンドのgrep
の部分は、64ビットLinuxバイナリのチェックサムとファイル名を含む行を出力し、その行を次のコマンドにパイプ(|
)します。 SHA-256コマンドは、-c
で、その行のファイル名を持つファイルがその行のチェックサムと一致することを確認します。
コマンドを実行すると、アーカイブがOK
であることが示されます。 そうでない場合は、ファイルを再ダウンロードしてみてください。
Outputvault_0.9.5_linux_amd64.zip: OK
チェックサムの検証が完了したら、unzip
コマンドをインストールして、アーカイブを解凍できるようにします。 まず、パッケージリポジトリが最新であることを確認してください。
- sudo apt-get update
- sudo apt-get install unzip
次に、Vaultバイナリを作業ディレクトリに解凍します。
- unzip vault_*.zip
OutputArchive: vault_0.9.5_linux_amd64.zip
inflating: vault
Vault実行可能ファイルをシステムのPATH
のディレクトリに移動して、シェルからアクセスできるようにします。
- sudo cp vault /usr/local/bin/
最後に、バイナリにLinux機能フラグを設定します。 これにより、バイナリがその特権を不必要に上げることなくメモリロックを実行できるようになるため、セキュリティが強化されます。
- sudo setcap cap_ipc_lock=+ep /usr/local/bin/vault
これで、vault
コマンドを使用できます。 Vaultのバージョンをチェックして、動作することを確認してください。
- vault --version
OutputVault v0.7.2 ('d28dd5a018294562dbc9a18c95554d52b5d12390')
Vault実行可能ファイルはサーバーにインストールされているため、次のステップは、システムサービスとして実行するようにVault実行可能ファイルを構成することです。
ステップ2—Vaultユニットファイルを作成する
SystemdはUbuntuのinitシステムであり、とりわけシステムのサービスを管理します。 Vaultをシステムサービスとして設定するには、次のものを設定する必要があります。
- Vaultデーモンを次のように実行するためのシステムユーザー
- Vaultの情報を保存するデータディレクトリ
- Vaultの構成ファイル
systemd
ユニットファイル自体。
注:このチュートリアルでは、ファイルシステムバックエンドを使用して、暗号化されたシークレットを/var/lib/vault
のローカルファイルシステムに保存します。 これは、複製する必要のないローカルまたは単一サーバーのデプロイメントに適しています。 Consulバックエンドなどの他のVaultバックエンドは、暗号化されたシークレットを分散キー/値ストア内に保存します。
まず、vaultシステムユーザーを作成します。
- sudo useradd -r -d /var/lib/vault -s /bin/nologin vault
ここでは、ユーザーのホームディレクトリとして/var/lib/vault
を使用します。 これは、Vaultデータディレクトリとして使用されます。 また、シェルを/bin/nologin
に設定して、ユーザーを非対話型システムアカウントとして制限します。
/var/lib/vault
の所有権をvaultユーザーとvaultグループに排他的に設定します。
- sudo install -o vault -g vault -m 750 -d /var/lib/vault
次に、Vaultの構成ファイル/etc/vault.hcl
を設定しましょう。 これを使用して、暗号化されたシークレットが保存される場所など、Vaultのさまざまなオプションを制御します。
nano
またはお好みのテキストエディタを使用してvault.hcl
を作成します。
- sudo nano /etc/vault.hcl
以下をファイルに貼り付け、必ず独自のドメイン名に置き換えてください。
backend "file" {
path = "/var/lib/vault"
}
listener "tcp" {
tls_disable = 0
tls_cert_file = "/etc/letsencrypt/live/example.com/fullchain.pem"
tls_key_file = "/etc/letsencrypt/live/example.com/privkey.pem"
}
この構成ファイルは、暗号化されたシークレットをディスク上の/var/lib/vault
に保存するようにVaultに指示し、VaultがLet’sEncryptチュートリアルから生成された証明書を使用してHTTPS経由で接続をリッスンする必要があることを示します。
ファイルを保存して閉じ、 vault ユーザーにのみ読み取りを許可して、Vault構成ファイルのアクセス許可を保護します。
- sudo chown vault:vault /etc/vault.hcl
- sudo chmod 640 /etc/vault.hcl
次に、Systemdに永続的なVaultデーモンを管理させるために、/etc/systemd/system/vault.service
にユニットファイルを作成します。
- sudo nano /etc/systemd/system/vault.service
以下をコピーしてファイルに貼り付けます。 これにより、Vaultを永続的なシステムサービスデーモンとしてバックグラウンドで実行できます。
[Unit]
Description=a tool for managing secrets
Documentation=https://vaultproject.io/docs/
After=network.target
ConditionFileNotEmpty=/etc/vault.hcl
[Service]
User=vault
Group=vault
ExecStart=/usr/local/bin/vault server -config=/etc/vault.hcl
ExecReload=/usr/local/bin/kill --signal HUP $MAINPID
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
Capabilities=CAP_IPC_LOCK+ep
SecureBits=keep-caps
NoNewPrivileges=yes
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target
サービスユニットオプションの完全なリストは広範囲にわたっていますが、上記の定義で注意すべき最も重要な構成オプションは次のとおりです。
ConditionFileNotEmpty
は、/etc/vault.hcl
構成ファイルが存在することを確認します。User
およびGroup
は、Vaultデーモンが実行されるユーザー権限を制御します。ExecStart
。これは、以前にインストールした実行可能ファイルを指し、サービスの実行を開始する対象を定義します。ExecReload
。これは、Vaultが構成ファイルをリロードするときに呼び出されます。たとえば、systemctl reload vault
を実行している場合などです。[Install]
。これにより、起動時にこのサービスを永続的に実行できるため、再起動後に手動で起動する必要がありません。
最後に、Vaultには、Certbotで作成した証明書を読み取るためのアクセス許可が必要です。 デフォルトでは、これらの証明書と秘密鍵にはrootからのみアクセスできます。 これらを安全に利用できるようにするために、pkiという特別なグループを作成してこれらのファイルにアクセスします。 グループを作成してから、vaultユーザーを追加します。
ファイルを保存して閉じ、pkiグループを作成します。
- sudo groupadd pki
/etc/letsencrypt
ディレクトリ内の2つのディレクトリのアクセス許可を更新して、pkiグループがコンテンツを読み取れるようにします。
- sudo chgrp pki /etc/letsencrypt/{archive,live}
- sudo chmod g+rx /etc/letsencrypt/{archive,live}
次に、vaultユーザーをpkiグループに追加します。 これにより、Vaultが証明書にアクセスできるようになり、HTTPSを介して安全にリクエストを処理できるようになります。
- sudo gpasswd -a vault pki
便宜上の最後のステップとして、/etc/hosts
にルールを追加して、Vaultへのリクエストをlocalhost
に送信します。
デフォルトでは、Vaultはループバックインターフェイス(lo
、またはアドレス127.0.0.1
)からの要求のみをリッスンします。 これは、サービスが適切に保護される前に、サービスがパブリックインターネットに公開されないようにするためです。 これは後で更新できますが、今のところ、この構成変更により、vault
コマンドを使用して、HTTPSで保護されたドメイン名を正しく解決できるようになります。
次のコマンドのexample.com
を、Let’sEncrypt証明書を取得したドメインに置き換えます。
- echo 127.0.0.1 example.com | sudo tee -a /etc/hosts
これにより、127.0.0.1 example.com
行が/etc/hosts
に追加され、example.com
へのHTTPリクエストがlocalhost
にルーティングされるようになります。
Vault実行可能ファイルがセットアップされ、サービスファイルが書き込まれ、Vault構成ファイルが完成したら、Vaultを起動してシークレットストアを初期化する準備が整いました。
ステップ3—Vaultを初期化する
Vaultを最初に起動すると、初期化されません。つまり、データを取得して保存する準備ができていません。
Vaultを初めて起動すると、暗号化されたシークレットを実際に保存するバックエンドも初期化されません。 Vaultシステムサービスを開始してバックエンドを初期化し、Vault自体の実行を開始します。
- sudo systemctl start vault
クイックチェックを実行して、サービスが正常に開始されたことを確認できます。
- sudo systemctl status vault
そのコマンドの出力には、プロセスIDやリソースの使用状況など、実行中のサービスに関するいくつかの情報が含まれている必要があります。 次の行が出力に含まれていることを確認してください。これは、サービスが正しく実行されていることを示しています。
Output. . .
Active: active (running)
. . .
サービスがアクティブでない場合は、コマンドの出力の最後にある付随するログ行を調べて、Vaultの出力を確認してください。これは、問題を特定するのに役立ちます。
次に、vault
コマンドにVaultサーバーへの接続方法を指示する環境変数を設定します。 ここでは、Vaultはローカルループバックインターフェイスでのみリッスンするように構成されているため、VAULT_ADDR
環境変数をローカルHTTPSエンドポイントに設定します。
- export VAULT_ADDR=https://example.com:8200
vault
コマンドがデーモンと通信できるようになりました。 HTTPS証明書を適切に検証するには、単にlocalhost
または127.0.0.1
ではなく実際のホスト名を定義する必要があることに注意してください。
ボールトのステータスを確認して、ボールトが初期化されていない状態にあることを確認します。
- vault status
サーバーは、サーバーがまだ初期化されていないことを示す400エラーを返す必要があります。
OutputError checking seal status: Error making API request.
URL: GET https://example.com:8200/v1/sys/seal-status
Code: 400. Errors:
* server is not yet initialized
Vaultが初期化時に公開する情報は2つあり、他の時点では利用できません。
- 初期ルートトークン。 これは、Vault展開に対するルート権限に相当し、すべてのVaultポリシー、マウントなどの管理を可能にします。
- キーを開封します。 これらは、デーモンの起動時にVaultのシールを解除するために使用されます。これにより、Vaultデーモンがバックエンドシークレットストアを復号化できるようになります。
より具体的には、Vaultの開封プロセスは、キー共有によって形成されたキーを使用してバックエンドを復号化します。 つまり、Vaultを初期化するときに、作成する開封キーの数と、Vaultを正常に開封するために開封時に必要な数を選択できます。
アンシールパラメータの一般的な単純な値は、3つのキーを作成し、アンシール時にそれらのキーのうち少なくとも2つを必要とすることです。 これにより、重要なキー共有を分離して別々の場所に保存し、侵害したキー共有がVaultの開封に十分でないことを確認できます。
つまり、Vaultを起動するたびに、サービスを使用可能にして使用できるようにするために、少なくとも2つの開封キーが必要になります。 封印されている間、実際の秘密の値を保存するファイルは暗号化されたままになり、アクセスできなくなります。
前述のパラメータを使用してVaultを初期化します。
- vault init -key-shares=3 -key-threshold=2
各アンシールトークンと最初のルートトークンを安全な方法で保存します。 たとえば、1つのオプションは、1つの開封キーをパスワードマネージャーに保存し、別のキーをUSBドライブに保存し、別のキーをGPG暗号化ファイルに保存することです。
新しく作成された開封トークンを使用して、Vaultを開封できるようになりました。 1つのキーを使用して開封することから始めます。
- vault operator unseal
コマンドは、開封トークンを要求します。
OutputKey (will be hidden):
入力後、コマンドからの出力は、開封が進行中であることを示しますが、Vaultを使用する準備ができるまでにもう1つの開封キーが必要です。
OutputSealed: true
Key Shares: 3
Key Threshold: 2
Unseal Progress: 1
Unseal Nonce: 3bdc838e-1b74-bc13-1d6f-c772f1694d83
unseal
コマンドを再実行してください。
- vault operator unseal
そして、すでに使用したものとは異なるトークンを入力します。
OutputKey (will be hidden):
コマンドの出力は、開封プロセスが正常に完了したことを示しています。
OutputSeal Type shamir
Sealed false
Total Shares 3
Threshold 2
Version 0.9.5
Cluster Name vault-cluster-5511b3ff
Cluster ID 53522534-8ee1-8aec-86db-e13e4a499dd0
HA Enabled false
これでVaultは開封され、使用できるようになりました。 これらの開封手順は、Vaultを起動または再起動するたびに必要です。
ただし、開封は、トークンによって認証されるVaultとの通常の相互作用(値の読み取りや書き込みなど)とは異なるプロセスです。 最後のステップでは、シークレット値を格納し、Vaultの特定のパスに対して読み取り/書き込みを行うために必要なアクセストークンとポリシーを作成します。
ステップ4—秘密の読み取りと書き込み
Vaultのドキュメントにはいくつかのシークレットバックエンドが列挙されていますが、この例では汎用シークレットバックエンドを使用します。 このバックエンドは、単純なキーと値のペアをVaultに格納します。
まず、使いやすさのために、以前に生成されたルートトークンをシェル変数に保存します。
- root_token=your_root_token_here
まず、Vault内のパスに値を書き込みます。
- VAULT_TOKEN=$root_token vault write secret/message value=mypassword
このコマンドでは、secret/
プレフィックスは、secret
パスにマウントされたgeneric
バックエンドに書き込み、キーvalue
をに格納していることを示します。パスmessage
の値はmypassword
です。 スーパーユーザー権限を持つルートトークンを使用して、一般的なシークレットを記述しました。
実際のシナリオでは、外部ツールが使用できるAPIキーやパスワードなどの値を保存できます。 ルートトークンを使用してシークレット値を再度読み取ることもできますが、単一のシークレットに対する読み取り専用のアクセス許可を持つ特権の低いトークンを生成することを示しています。
policy.hcl
というファイルを作成します。
- nano policy.hcl
作業ディレクトリのシークレットパスへの読み取り専用アクセスを定義する次のVaultポリシーをファイルに入力します。
path "secret/message" {
capabilities = ["read"]
}
ファイルを保存して閉じてから、このポリシーをVaultに書き込みます。 次のコマンドは、ポリシーの権限を持つmessage-readonly
という名前のポリシーを作成します。
- VAULT_TOKEN=$root_token vault policy write message-readonly policy.hcl
これで、ポリシーで指定された権限でトークンを作成できます。
- VAULT_TOKEN=$root_token vault token create -policy="message-readonly"
出力は次のようになります。
OutputKey Value
--- -----
token your_token_value
token_accessor your_token_accessor
token_duration 768h0m0s
token_renewable true
token_policies [default message-readonly]
token
の値をapp_token
という変数に保存します。
- app_token=your_token_value
app_token
の値を使用して、パスsecret/message
に格納されているデータにアクセスできます(Vaultには他の値はありません)。
- VAULT_TOKEN=$app_token vault read secret/message
OutputKey Value
--- -----
refresh_interval 768h0m0s
value mypassword
この非特権トークンが、Vaultにシークレットを一覧表示するなど、他の操作を実行できないことをテストすることもできます。
- VAULT_TOKEN=$app_token vault list secret/
OutputError reading secret/: Error making API request.
URL: GET https://example.com:8200/v1/secret?list=true
Code: 403. Errors:
* permission denied
これにより、特権の低いアプリトークンが、Vaultポリシーで明示的に指定されているもの以外の破壊的なアクションを実行したり、他の秘密の値にアクセスしたりできないことが確認されます。
結論
この記事では、Ubuntu 16.04にVaultをインストール、構成、およびデプロイしました。 このチュートリアルでは、非特権トークンの使用についてのみ説明しましたが、Vaultのドキュメントには、シークレットを保存およびアクセスするための追加の方法と代替認証方法に関する詳細情報があります。
これらの手順では、Vaultをかなり基本的な方法で展開および使用する方法の概要を説明しているため、 Vaultのドキュメントを読み、必要に応じて適切な構成変更を行ってください。 本番環境に対応した変更には、次のものがあります。
-
日常的に使用するための特権の低いトークンを生成します。 これらのトークンが使用する必要のある特定のポリシーは特定のユースケースによって異なりますが、前述の
app_token
は、制限付き特権のトークンとポリシーを作成する方法を示しています。 -
Vaultがチームサービスの一部として展開されている場合、各チームメンバーの開封キーを使用してVaultを初期化すると、複数のチームメンバーがプロセスに参加している場合にのみVaultのストレージを復号化できます。