1.概要
このチュートリアルでは、最新のアプリケーションアーキテクチャで機密情報を安全に管理するために使用される一般的なツールであるHashicorpのVaultについて説明します。
ここで取り上げる主なトピックは次のとおりです。
-
Vaultはどのような問題を解決しようとしています
-
Vaultのアーキテクチャと主な概念
-
簡単なテスト環境の設定
-
コマンドラインツールを使ってVaultと対話する
2.機密情報に関する問題
Vaultを掘り下げる前に、解決しようとしている問題、つまり機密情報管理について理解しよう。
-
ほとんどのアプリケーションは、正しく機能するために機密データにアクセスする必要があります** 。たとえば、電子商取引アプリケーションでは、データベースに接続するためにユーザ名/パスワードがどこかに設定されている場合があります。支払いゲートウェイ、物流、その他のビジネスパートナーなど、他のサービスプロバイダと統合するためのAPIキーも必要になる場合があります。
データベース認証情報とAPIキーは、安全な方法で保存してアプリケーションで利用できるようにするために必要な機密情報の例です。
簡単な解決策は、これらの認証情報を設定ファイルに保存して起動時に読み取ることです。ただし、この方法の問題は明らかです。 このファイルにアクセスできる人はだれでも、私たちのアプリケーションが持っているものと同じデータベース特権を共有します - 通常、すべての保存されたデータへのフルアクセスを彼女に与えます。
これらのファイルを暗号化することで、物事を少し難しくすることができます。ただし、この方法では、全体的なセキュリティに関してはそれほど多くはなりません。
主に、アプリケーションはマスターキーにアクセスできる必要があるためです。
暗号化をこのように使用した場合、「誤った」安心感しか得られません。
現代のアプリケーションやクラウド環境では、さらに複雑さが増す傾向があります。分散サービス、複数のデータベース、メッセージングシステムなど、すべてに機密情報が少しずつ行き渡っているため、セキュリティ侵害の危険性が高まります。
それで、私たちは何ができますか?それをVaultしましょう!
3. Vaultとは何ですか?
Hashicorp Vaultは、機密情報の管理の問題、つまりVaultの用語でいうと 秘密 を扱います。 ** この文脈で「管理する」とは、Vaultが機密情報のあらゆる側面を管理することを意味します。
HashicorpはVaultの2つのバージョンを提供しています。この記事で使用されているオープンソース版は、商用環境でも自由に使用できます。さまざまなSLAでのテクニカルサポートや、HSM(Hardware Security Module)サポートなどの追加機能を含む有料版もあります。
3.1. 建築
Vaultのアーキテクチャは非常に単純です。その主なコンポーネントは以下のとおりです。
-
永続化バックエンド - すべての秘密のための記憶域
-
クライアントの要求を処理して操作を実行するAPIサーバー
秘密 ** いくつかの____secretエンジン、サポートされている秘密の種類ごとに1つ
タイプ
すべての秘密処理をVaultに委任することで、セキュリティ上の問題を軽減できます。
-
私たちのアプリケーションはもうそれらを保存する必要はありません。ただVaultに聞いてください。
必要なときに破棄してください ** 私たちは短期間の秘密を使うことができます。
攻撃者が盗まれた秘密を使用できる場所」
Vaultは、ストアに書き込む前にすべてのデータを暗号化キーで暗号化します。この暗号化キーは、起動時にのみ使用されるマスターキーという別のキーで暗号化されています。
Vaultの実装における重要な点は、マスターキーをサーバーに保存しないことです。 これは、起動後にVaultでも保存されたデータにアクセスできないことを意味します。 この時点で、Vaultインスタンスは「シールされた」状態にあると言われています。
後で、マスターキーを生成してVaultインスタンスを開封するのに必要な手順を実行します。
封印が解除されると、VaultはAPI要求を受け入れる準備が整います。もちろん、これらの要求には認証が必要です。これにより、Vaultがクライアントを認証する方法と、クライアントが実行できることまたは実行できないことを決定する方法がわかります。
3.2. 認証
-
Vaultの秘密にアクセスするには、クライアントはサポートされている方法の1つを使って自分自身を認証する必要があります。最も簡単な方法はトークンを使用します。トークンは特別なHTTPヘッダを使用してすべてのAPIリクエストで送信される単なる文字列です。
最初にインストールしたときに、Vaultは自動的に「ルートトークン」を生成します。
このトークンはLinuxシステムのrootスーパーユーザーと同等なので、その使用は最小限に制限する必要があります。ベストプラクティスとして、このルートトークンを使用して、特権の少ない他のトークンを作成してから取り消すようにしてください。ただし、これは問題にはなりません。後で封印解除キーを使用して別のルートトークンを生成できるためです。
Vaultは、LDAP、JWT、TLS証明書などの他の認証メカニズムもサポートしています。これらのメカニズムはすべて、基本的なトークンメカニズムの上に構築されています。Vaultがクライアントを検証すると、トークンが提供され、それを使用して他のAPIにアクセスできます。
トークンにはいくつかのプロパティが関連付けられています。主な特性は次のとおりです。
-
関連する Policies のセット(次のセクションを参照)
-
有効期間
-
更新できるかどうか
-
最大使用回数
特に指示がない限り、Vaultによって作成されたトークンは親子関係を形成します。子トークンは、親トークンと同じレベル以下の特権を持つことができます。
逆のことは言えません。制限的なポリシーを使って子トークンを作成することができます(通常は作成しています)。
-
トークンを無効にすると、すべての子トークンとその子孫も無効になります** 。
3.3. ポリシー
-
ポリシーは、クライアントがどの秘密にアクセスできるのか、そしてそれがどの操作を実行できるのかを正確に定義します。単純なポリシーがどのように見えるかを見てみましょう。
path "secret/accounting" {
capabilities =["read"]}
ここでは、ポリシーを定義するためにHCL(Hashicorpの構成言語)構文を使用しました。 Vaultはこの目的のためにJSONもサポートしていますが、私たちの例では読みやすいのでHCLを使います。
-
Vaultのポリシーは「デフォルトで拒否」** です。このサンプルポリシーに添付されているトークンは、 secret/accounting の下に格納されているシークレットへのアクセスを取得します。作成時に、トークンを複数のポリシーに添付することができます。これは非常に便利です。小さいポリシーを作成してテストし、必要に応じてそれらを適用できるからです。
ポリシーのもう1つの重要な側面は、遅延評価を利用することです。これは、与えられたポリシーを更新することができ、すべてのトークンが即座に影響を受けることを意味します。
これまでに説明したポリシーは、アクセス制御リストポリシー、またはACLポリシーとも呼ばれます。 Vaultは、EGPポリシーとRGPポリシーの2つの追加のポリシータイプもサポートしています。これらは有料版でのみ利用可能で、https://www.vaultproject.io/docs/enterprise/sentinel/index.html[Sentinel]サポートで基本的なポリシー構文を拡張します。
利用可能であれば、これにより、ポリシーで、時刻、複数の認証要素、クライアントネットワークの発信元などの追加の属性を考慮に入れることができます。たとえば、営業時間内にのみ特定の秘密へのアクセスを許可するポリシーを定義できます。
ポリシー構文の詳細については、https://www.vaultproject.io/docs/concepts/policies.html[Vaultのドキュメント]を参照してください。
4.秘密の種類
Vaultは、さまざまなユースケースに対応するさまざまな種類の秘密をサポートしています。
-
Key-Value: 単純な静的なKey-Valueペア
-
動的に生成された認証情報 :リクエストによりVaultによって生成されます
クライアントによる ** 暗号鍵 :で暗号機能を実行するために使用されます。
クライアントデータ
各秘密タイプは、以下の属性によって定義されます。
-
REST APIプレフィックスを定義する mount point、
-
対応するAPIを通じて公開される一連の操作
-
設定パラメータのセット
与えられた秘密のインスタンスは、ファイルシステムのディレクトリツリーのように、 path を介してアクセスできます。 ** このパスの最初の要素は、このタイプのすべての秘密が置かれているマウントポイントに対応します。
たとえば、文字列 __secret/my-application は、 my-application__のキーと値のペアを見つけることができるパスに対応しています。
4.1. キーバリューの秘密
-
Key-Valueシークレットは、その名前が示すように、指定されたパスの下で使用可能な単純なペアです** 。たとえば、 secret = my-applicationというパスの下に foo = bar というペアを格納できます。 __
後で、同じパスを使用して同じペアを取得します。複数のペアを同じパスに格納できます。
Vaultは3種類のKey-Valueシークレットをサポートします。
-
非バージョンキーペア 、ここで更新は既存の値を置き換えます
-
古いバージョンの設定可能な数までを維持する Versioned Key-Pairs
バージョン ** Cubbyhole 、値がバージョン管理されていない特別なタイプのキーペア
指定された アクセストークン にスコープされています(後で詳しく説明します)。
Key-Value秘密は本質的に静的であるため、それらに関連する有効期限の概念はありません。この種の秘密の主な使用例は、APIキーなどの外部システムにアクセスするための資格情報を格納することです。
そのようなシナリオでは、資格情報の更新は半手動のプロセスであり、通常は誰かに新しい資格情報を取得し、新しい値を入力するためにVaultのコマンドラインまたはそのUIを使用する必要があります。
4.2. 動的に生成された秘密
-
アプリケーションから要求されたときに動的秘密はVaultによってその場で生成されます。 Vaultは、次のようないくつかの種類の動的秘密をサポートしています。
-
データベース認証情報
-
SSHキーペア
-
X.509証明書
-
AWS認証情報
-
Google Cloudサービスアカウント
-
Active Directoryアカウント
これらはすべて同じ使用パターンに従います。まず、関連するサービスへの接続に必要な詳細情報を使ってシークレットエンジンを構成します。
それから、1つ以上の____rolesを定義します。これは、実際の秘密の作成を表します。
データベースシークレットエンジンを例に取りましょう。まず、新しいユーザーを作成するために、管理者権限を持つ既存のユーザーからの資格情報など、すべてのユーザーデータベース接続の詳細を使用してVaultを構成する必要があります。
次に、新しいユーザーの作成に使用された実際のSQL文を含む1つ以上のロール(データベースロールではなくボールトロール)を作成します。これらには通常、ユーザー作成ステートメントだけでなく、スキーマオブジェクト(テーブル、ビューなど)へのアクセスに必要なすべての必須 grant ステートメントも含まれます。
-
クライアントが対応するAPIにアクセスすると、Vaultは提供されたステートメントを使用してデータベースに新しい一時ユーザーを作成し、その資格情報を返します** 。その後、クライアントはこれらの資格情報を使用して、要求された役割の有効期間属性によって定義された期間中にデータベースにアクセスできます。
資格情報が有効期限に達すると、Vaultはこのユーザーに関連付けられている特権を自動的に取り消します。クライアントは、これらの認証情報を更新するようにVaultに要求することもできます。更新プロセスは、特定のデータベースドライバによってサポートされ、関連するポリシーによって許可されている場合にのみ発生します。
4.3. 暗号化キー
タイプの秘密エンジンは、暗号化、復号化、署名などの暗号機能を処理します。 ** これらの操作はすべて、Vaultによって内部的に生成および保存された暗号化キーを使用します。明示的に指示がない限り、Vaultは特定の暗号化キーを公開することはありません。
関連付けられたAPIにより、クライアントはVaultのプレーンテキストデータを送信し、それを暗号化したものを受信できます。逆も可能です。暗号化されたデータを送信して元のテキストを元に戻すことができます。
現在、このタイプのエンジンは Transit エンジンのみです。
このエンジンは、RSAやECDSAなどの一般的なキータイプをサポートし、__Convergent Encryptionもサポートします。
たとえば、トランザクションログテーブル内のクレジットカード番号を暗号化するためにこのモードを使用できます。収束暗号化では、新しいトランザクションを挿入するたびに、暗号化されたクレジットカードの値が同じになるため、レポート作成、検索などに通常のSQLクエリを使用できます。
5.ボールトの設定
このセクションでは、Vaultの機能をテストするためにローカルテスト環境を作成します。
Vaultの展開は簡単です。https://www.vaultproject.io/downloads.html[パッケージをダウンロード]をクリックします。これは、オペレーティングシステムに対応し、その実行可能ファイル(Windowsの場合は __vault または __vault.exe)をPATH上のディレクトリに展開します。
-
この実行ファイルはサーバを含み、標準のクライアントでもあります。
こちらには公式のDockerイメージもあります が、ここではカバーしません。
Vaultは development モードをサポートしています。これはクイックテストやコマンドラインツールに慣れるためには賢い方法ですが、実際のユースケースにはあまりにも単純すぎます。
代わりに、ファイルベースの永続ストレージを使用してHTTPSをセットアップするので、問題の原因となる可能性がある実際の構成の詳細について調べることができます。
5.1. Vaultサーバの起動
Vaultは、HCLまたはJSON形式を使用して設定ファイルを使用します。次のファイルは、ファイルストレージと自己署名証明書を使用してサーバーを起動するために必要なすべての設定を定義しています。
storage "file" {
path = "./vault-data"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls__cert__file = "./src/test/vault-config/localhost.cert"
tls__key__file = "./src/test/vault-config/localhost.key"
}
それでは、Vaultを起動しましょう。コマンドシェルを開き、設定ファイルを含むディレクトリに移動して次のコマンドを実行します。
$ vault server -config ./vault-test.hcl
Vaultが起動し、いくつかの初期化メッセージが表示されます。そのバージョン、設定の詳細、そしてAPIが利用可能なアドレスが含まれます。これで終わりです - 私たちのVaultサーバは稼働しています。
5.2. ボールトの初期化
私たちのVaultサーバは現在稼働していますが、これが最初の稼働なので初期化する必要があります。
新しいシェルを開き、これを実現するために次のコマンドを実行しましょう。
$ export VAULT__ADDR=https://localhost:8200
$ export VAULT__CACERT=./src/test/vault-config/localhost.cert
$ vault operator init
ここではいくつかの環境変数を定義したので、パラメータとして毎回Vaultに渡す必要はありません。
-
VAULT ADDR__:APIサーバーがリクエストを処理するベースURI
-
VAULT CACERT__:サーバーの証明書公開鍵へのパス
今回の場合は、 VAULT CACERT__を使用しているので、HTTPSを使用してVaultのAPIにアクセスできます。自己署名証明書を使用しているため、これが必要です。
通常、CA署名付き証明書にアクセスできる本番環境では、これは不要です。
上記のコマンドを発行した後、私達はこのようなメッセージを見るはずです:
Unseal Key 1: <key share 1 value>
Unseal Key 2: <key share 2 value>
Unseal Key 3: <key share 3 value>
Unseal Key 4: <key share 4 value>
Unseal Key 5: <key share 5 value>
Initial Root Token: <root token value>
... more messages omitted
最初の5行は、後でVaultのストレージを開封するために使用するマスターキー共有です。 Vaultは初期化中に表示されるマスターキー共有のみを表示し、それ以上は表示されないことに注意してください。 注意して安全に保存するか、サーバーを再起動すると秘密にアクセスできなくなります。**
また、後で必要になるので、 root token にも注意してください。
開封鍵とは異なり、 ルートトークンは後で 簡単に生成することができるので、すべての設定作業が完了したらそれを破棄しても安全です。後で認証トークンを必要とするコマンドを発行するので、ここではルートトークンを環境変数に保存しましょう。
$ export VAULT__TOKEN=<root token value> (Unix/Linux)
次のコマンドで初期化したので、サーバーのステータスを確認しましょう。
$ vault status
Key Value
--- -----
Seal Type shamir
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 0/3
Unseal Nonce n/a
Version 0.10.4
HA Enabled false
Vaultがまだ封印されていることがわかります。 「0/3」はVaultが3つの共有を必要としていることを意味しますが、これまでのところ何も取得していません。それでは先に進み、それを私たちの株で提供しましょう。
5.3. 金庫の開封
Vaultの封印を解除し、秘密のサービスを使い始めることができます。開封手続きを完了するには、5つの主要シェアのうち3つを提供する必要があります。
$ vault operator unseal <key share 1 value>
$ vault operator unseal <key share 2 value>
$ vault operator unseal <key share 3 value>
各コマンドを発行した後、金庫室は必要なシェア数を含む封印の進捗状況を印刷します。最後のキーシェアを送信すると、次のようなメッセージが表示されます。
Key Value
--- -----
Seal Type shamir
Sealed false
... other properties omitted
この場合、“ Sealed”プロパティは“ false”です。つまり、Vaultはコマンドを受け入れる準備ができています。
6. Vaultをテストする
このセクションでは、サポートされている2つのシークレットタイプ、Key/ValueとDatabaseを使用して、Vaultの設定をテストします。また、特定のポリシーを適用して新しいトークンを作成する方法も示します。
6.1. キーと値の秘密の使用
まず、秘密のKey-Valueペアを保存して読み返しましょう。 Vaultの初期化に使用されたコマンドシェルがまだ開いていると仮定して、次のコマンドを使用してこれらのペアを secret/fakebank パスの下に格納します。
$ vault kv put secret/fakebank api__key=abc1234 api__secret=1a2b3c4d
次のコマンドでいつでもこれらのペアを回復できます。
$ vault kv get secret/fakebank
======= Data =======
Key Value
--- -----
api__key abc1234
api__secret 1a2b3c4d
この簡単なテストは、Vaultが正常に機能していることを示しています。これでいくつかの追加機能をテストできます。
6.2. 新しいトークンを作成する
これまでは、リクエストを認証するためにルートトークンを使用してきました。ルートトークンは非常に強力であるため、より少ない特権とより短い有効期間を持つトークンを使用することがベストプラクティスと考えられています。
ルートトークンと同じように使用できる新しいトークンを作成しましょう。ただし、数分後に有効期限が切れます。
$ vault token create -ttl 1m
Key Value
--- -----
token <token value>
token__accessor <token accessor value>
token__duration 1m
token__renewable true
token__policies ["root"]identity__policies []policies ["root"]----
このトークンをテストして、以前作成したキーと値のペアを読み取ります。
[source,bash,gutter:,true]
$ export VAULT TOKEN=<token value> $ vault kv get secret/fakebank ======= Data ======= Key Value --- ----- api key abc1234 api__secret 1a2b3c4d
しばらく待ってからこのコマンドを再発行しようとすると、エラーメッセージが表示されます。 [source,bash,gutter:,true]
$ vault kv get secret/fakebank Error making API request.
URL: GET https://localhost:8200/v1/sys/internal/ui/mounts/secret/fakebank Code: 403. Errors:
-
permission denied
メッセージは私たちのトークンがもはや有効ではないことを示しています。 [[testing__policies]] ==== 6.3. テスト方針 前のセクションで作成したサンプルトークンは短命でしたが、それでも非常に強力です。今度はポリシーを使用して、より制限の厳しいトークンを作成しましょう。 たとえば、以前使用した__secret/fakebank__パスへの読み取りアクセスのみを許可するポリシーを定義しましょう。 [source,bash,gutter:,true]
$ cat > sample-policy.hcl <<EOF path "secret/fakebank" { capabilities =["read"]} EOF $ export VAULT__TOKEN=<root token> $ vault policy write fakebank-ro ./sample-policy.hcl Success! Uploaded policy: fakebank-ro
次のコマンドで、このポリシーでトークンを作成します。 [source,bash,gutter:,true]
$ export VAULT TOKEN=<root token> $ vault token create -policy=fakebank-ro Key Value --- ----- token <token value> token accessor <token accessor value> token duration 768h token renewable true token policies ["default" "fakebank-ro"]identity policies []policies ["default" "fakebank-ro"]----
これまでに行ったように、このトークンを使用して秘密の値を読みましょう。
$ export VAULT__TOKEN=<token value>
$ vault kv get secret/fakebank
======= Data =======
Key Value
--- -----
api__key abc1234
api__secret 1a2b3c4d
ここまでは順調ですね。予想通り、データを読むことができます。この秘密を更新しようとするとどうなるかを見てみましょう。
$ vault kv put secret/fakebank api__key=foo api__secret=bar
Error writing data to secret/fakebank: Error making API request.
URL: PUT https://127.0.0.1:8200/v1/secret/fakebank
Code: 403. Errors:
** permission denied
我々のポリシーでは明示的に書き込みを許可していないため、Vaultは403 - Access Deniedステータスコードを返します。
6.4. 動的データベース資格情報の使用
この記事の最後の例として、動的な認証情報を作成するためにVaultのデータベースシークレットエンジンを使用しましょう。ここでは、MySQLサーバーをローカルで利用できることと、「root」権限でアクセスできると仮定します。 account という単一のテーブルで構成される非常に単純なスキーマも使用します。
このスキーマと特権ユーザーの作成に使用されたSQLスクリプトは、ここから入手できます。
それでは、このデータベースを使用するようにVaultを設定しましょう。データベースシークレットエンジンはデフォルトでは有効になっていないので、先に進む前にこれを修正する必要があります。
$ vault secrets enable database
Success! Enabled the database secrets engine at: database/----
データベース構成リソースを作成します。
[source,bash,gutter:,true]
$ vault write database/config/mysql-fakebank \ plugin name=mysql-legacy-database-plugin \ connection url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/fakebank" \ allowed__roles="** " \ username="fakebank-admin" \ password="Sup&rSecre7!"
パス接頭辞__database/config__は、すべてのデータベース構成を格納する場所です。ここでは__mysql-fakebank__という名前を選択しているので、この設定がどのデータベースを参照しているのか簡単に判断できます。設定キーに関しては: ** __plugin__name:__使用するデータベースプラグインを定義します。の 利用可能なプラグイン名は https://www.vaultproject.io/docs/secrets/databases/index.html[Vault's]ドキュメント]** __connection__url__:これはプラグインによって使用されるテンプレートです。 データベースに接続します。 \ {\ {username}}と\ {\ {password}}に注目してください テンプレートプレースホルダー。データベースに接続すると、Vaultは これらのプレースホルダーを実際の値で置き換えます ** __allowed__roles__:(次に説明する)どのVaultロールを使用できるかを定義します この設定私たちの場合は「** 」を使用しているので、すべての人が利用できます。 役割 ** __ユーザー名 新規ユーザーの作成やその特権の取り消しなどのデータベース操作を実行する 最後の設定作業は、ユーザーの作成に必要なSQLコマンドを含むVaultデータベースロールリソースを作成することです。セキュリティ要件に応じて、必要な数のロールを作成できます。 ここでは、__fakebank__スキーマのすべてのテーブルへの読み取り専用アクセスを許可するロールを作成します。 [source,actionscript3,gutter:,true]
$ vault write database/roles/fakebank-accounts-ro \ db name=mysql-fakebank \ creation statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON fakebank.** TO '{{name}}'@'%';"
データベースエンジンは、パスプレフィックス____database/roles ____をロールを格納する場所として定義します。 __fakebank-accounts-ro__は、後で動的認証情報を作成するときに使用するロール名です。以下のキーも提供しています。 ** __db__name__:既存のデータベース構成の名前。に対応 設定を作成するときに使用したパスの最後の部分 リソース ** __creation__statements:__ Vaultが実行するSQL文テンプレートのリスト 新しいユーザーを作成するために使用します データベースロールとそれに対応する設定が準備できたら、次のコマンドで新しい動的認証情報を生成します。 [source,bash,gutter:,true]
$ vault read database/creds/fakebank-accounts-ro Key Value --- ----- lease id database/creds/fakebank-accounts-ro/0c0a8bef-761a-2ef2-2fed-4ee4a4a076e4 lease duration 1h lease__renewable true password <password> username <username>
__database/creds__プレフィックスは、利用可能な役割の資格情報を生成するために使用されます。 ____fakebank-accounts-ro ____roleを使用したので、返されるユーザー名/パスワードは__select__操作に制限されます。 これを確認するには、提供された資格情報を使用してデータベースに接続し、次にいくつかのSQLコマンドを実行します。 [source,bash,gutter:,true]
$ mysql -h 127.0.0.1 -u <username> -p fakebank Enter password: MySQL[fakebank]> select ** from account; … omitted for brevity 2 rows in set (0.00 sec) MySQL[fakebank]> delete from account; ERROR 1142 (42000): DELETE command denied to user 'v-fake-9xoSKPkj1'@'localhost' for table 'account'
** 最初の__select__が正常に完了したことがわかりますが、__delete__ステートメントを実行できませんでした** 。最後に、1時間待って同じ資格情報を使用して接続しようとすると、データベースに接続できなくなります。 Vaultはこのユーザーからすべての特権を自動的に取り消しました === 7.まとめ この記事では、それが取り組もうとしている問題、そのアーキテクチャー、そして基本的な使用法についてのいくつかの背景を含む、HashicorpのVaultの基本を探りました。 その過程で、私たちはフォローアップ記事で使用する、シンプルだが機能的なテスト環境を作成しました。 次の記事では、Vaultの非常に具体的なユースケースについて説明します。** Spring Bootアプリケーションのコンテキストで使用する** 。乞うご期待!