はじめに
HashiCorpのVaultが提供している Data Encryption (Transit Secret Backend)機能について公式ドキュメントを参考に動作を確認しましたので備忘録として残しておきます。
やったこと
Vaultの Data Encryption 機能を利用してにテキストの暗号化・復号化を行う。
HashiCorp Vaultとは?
HashiCorpが提供している機密情報の管理ツールです。
Data Encryption (Transit Secret Backend)とは?
Vaultにデータの暗号化、復号化を行わせる機能です。
この機能でVaultは暗号化復号化に利用するKeyの管理のみ行い、暗号化したデータは保持しません。
暗号化されたデータはVaultの呼び出し元で管理(DBなどに格納)する必要があります。
HashiCorpからRailsアプリ向けに提供されているvault-railsではこの機能が利用されてます。
参考
公式サイト
ドキュメント
Transit Secret Backend
Decrypt Data
事前準備
Transit Secret Backendを利用できるようにしておきます。
VaultをDevモードで起動
DevモードではVaultを停止させるとデータが消えてしまいますが、今回は動作確認のためDevモードで起動します。
$ vault server -dev
...
export VAULT_ADDR='http://127.0.0.1:8200'
...
Root Token: e301d832-a587-0092-7dec-eaf71369c2b3
...
環境変数の設定
Vaultがリクエストを受け付けるアドレスとTokenを環境変数に設定しておきます。
$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN='e301d832-a587-0092-7dec-eaf71369c2b3'
transitをマウント
transit機能を利用できるようにマウントしておきます。
$ vault mount transit
Keyを生成・削除
データの暗号化・復号化に利用するKeyを生成します。
Keyの名称はmy-key
とします。
Create Key (aes256-gcm96)
暗号化方式のデフォルトはaes256-gcm96
です。
typeオプションを指定しないでKeyを生成するとaes256-gcm96
でKeyが生成されます。
typeオプションを指定することで ecdsa-p256
, ed25519
も指定可能です。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
$VAULT_ADDR/v1/transit/keys/my-key
or
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "type": "aes256-gcm96" }' \
$VAULT_ADDR/v1/transit/keys/my-key
Create Key (ecdsa-p256)
typeオプション(暗号化方式)にecdsa-p256
を指定してKeyを生成。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "type": "ecdsa-p256" }' \
$VAULT_ADDR/v1/transit/keys/my-key
Create Key (ed25519)
typeオプション(暗号化方式)にed25519
を指定してKeyを生成。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "type": "ed25519" }' \
$VAULT_ADDR/v1/transit/keys/my-key
Read Key
Keyの情報を確認できます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/transit/keys/my-key
{
"request_id": "5d0e4a83-da8f-80b8-0ffb-d9cd9158cc0b",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"deletion_allowed": false,
"derived": false,
"exportable": false,
"keys": {
"1": 1506730923
},
"latest_version": 1,
"min_decryption_version": 1,
"min_encryption_version": 0,
"name": "my-key",
"supports_decryption": true,
"supports_derivation": true,
"supports_encryption": true,
"supports_signing": false,
"type": "aes256-gcm96"
},
"wrap_info": null,
"warnings": null,
"auth": null
}
List Keys
Keyの一覧を取得できます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request LIST \
$VAULT_ADDR/v1/transit/keys
{
"request_id": "bf844792-a14c-4e6e-20f6-b10a0f1af141",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"keys": [
"my-key"
]
},
"wrap_info": null,
"warnings": null,
"auth": null
}
Delete Key
Keyを削除します。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request DELETE \
$VAULT_ADDR/v1/transit/keys/my-key
Keyの削除が許可されてない場合、400エラーと以下のメッセージが返却されます。
削除するためにはKeyのdeletion_allowed
オプションをtrue
に変更する必要があります。
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"error deleting policy my-key: deletion is not allowed for this policy"
]
}
Update Key Configuration
Keyの設定を変更します。
Keyの削除を許可する場合はdeletion_allowed
オプションをtrue
にして実行します。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "deletion_allowed": true }' \
$VAULT_ADDR/v1/transit/keys/my-key/config
データの暗号化・復号化
生成したKeyを利用してデータの暗号化、復号化を実施します。
plaintext
暗号化したいデータ(plaintext)を指定して暗号化します。
plaintextはbase64でエンコードされてる必要があります。
base64 encode
vaultには暗号化対象のデータをbase64で渡す必要があるのでbase64でエンコードしておきます。
$ echo "テスト" | base64
44OG44K544OICg==
Encrypt Data
base64化したテキスト(plaintext
)をVaultに暗号化させます。
暗号化されたデータはレスポンスのciphertext
部分で返却されます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "plaintext": "44OG44K544OICg==" }' \
$VAULT_ADDR/v1/transit/encrypt/my-key
{
"request_id": "3b15a62d-e5d5-dc9e-e60d-1763969dccf4",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"ciphertext": "vault:v1:iwDQyBSyXgo+MutoHXPT76MpVek78fxMQW1LXI3C3C++EVIJyFY="
},
"wrap_info": null,
"warnings": null,
"auth": null
}
Decrypt Data
暗号化したデータ(ciphertext
)をVaultに復号化させます。
復号化されたデータはレスポンスのplaintext
部分で返却されます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "ciphertext": "vault:v1:iwDQyBSyXgo+MutoHXPT76MpVek78fxMQW1LXI3C3C++EVIJyFY=" }' \
$VAULT_ADDR/v1/transit/decrypt/my-key
{
"request_id": "7857e0c1-1f68-73e3-c54d-09fdfafd684f",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"plaintext": "44OG44K544OICg=="
},
"wrap_info": null,
"warnings": null,
"auth": null
}
base64 decode
Vaultから返却されたデータ(plaintext
)をbase64でデコードすると元のテキストに戻ります。
$ echo "44OG44K544OICg==" | base64 -D
テスト
補足
暗号化
plaintext
がbase64でエンコードされてないと暗号化できません。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "plaintext": "テスト" }' \
$VAULT_ADDR/v1/transit/encrypt/my-key
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"failed to base64-decode plaintext"
]
}
復号化
ciphertext
の値が誤っていると復号化できなくなります。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "ciphertext": "vault:v1:iwDQyBSyXgo+MutoHXPT76MpVek78fxMQW1LXI3C3D++EVIJyFY=" }' \
$VAULT_ADDR/v1/transit/decrypt/my-key
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"invalid ciphertext: unable to decrypt"
]
}
plaintext & context
Keyを生成する際にderived
オプションにtrue
を指定した場合、plaintext
に加えてcontext
が付与されてないと暗号化・復号化が出来ないようになります。
Keyの生成
derived
オプションにtrue
を指定してKeyを生成します。
Keyの名称はmy-key2
とします。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "derived": true }' \
$VAULT_ADDR/v1/transit/keys/my-key2
base64 encode
context
とplaintext
をbase64でエンコードしておきます。
$ echo "キー" | base64
44Kt44O8Cg==
$ echo "テスト" | base64
44OG44K544OICg==
Encrypt Data
context
とplaintext
を渡してVaultに暗号化させます。
暗号化したデータはciphertext
として返却されます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "context":"44Kt44O8Cg==" , "plaintext": "44OG44K544OICg==" }' \
$VAULT_ADDR/v1/transit/encrypt/my-key2
{
"request_id": "29c41d1b-ec94-3800-af4b-f57b2aa58063",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"ciphertext": "vault:v1:WAJUPIOn65NV7dI+Zlbcr0z8XJvz1AqYQYJN6+yzGT+CVoKuK3s="
},
"wrap_info": null,
"warnings": null,
"auth": null
}
Decrypt Data
context
とplaintext
を渡してVaultに復号化させます。
復号化したデータはplaintext
として返却されます。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "context":"44Kt44O8Cg==", "ciphertext": "vault:v1:WAJUPIOn65NV7dI+Zlbcr0z8XJvz1AqYQYJN6+yzGT+CVoKuK3s=" }' \
$VAULT_ADDR/v1/transit/decrypt/my-key2
{
"request_id": "15ea30d1-9c0c-e711-b947-3ace1a55c622",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"plaintext": "44OG44K544OICg=="
},
"wrap_info": null,
"warnings": null,
"auth": null
}
base64 decode
Vaultから返却されたデータをbase64でデコードすると元のテキストに戻ります。
$ echo "44OG44K544OICg==" | base64 -D
テスト
補足
暗号化
derived
オプションが有効なKeyではcontext
を指定しないと暗号化できません。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "plaintext": "44OG44K544OICg==" }' \
$VAULT_ADDR/v1/transit/encrypt/my-key2
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"missing 'context' for key derivation; the key was created using a derived key, which means additional, per-request information must be included in order to perform operations with the key"
]
}
復号化
derived
オプションが有効なKeyではcontext
を指定しないと復号化できません。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "ciphertext": "vault:v1:WAJUPIOn65NV7dI+Zlbcr0z8XJvz1AqYQYJN6+yzGT+CVoKuK3s=" }' \
$VAULT_ADDR/v1/transit/decrypt/my-key2
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"missing 'context' for key derivation; the key was created using a derived key, which means additional, per-request information must be included in order to perform operations with the key"
]
}
context
が暗号化した時と不一致でも復号化できません。
$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "context":"44Kr44O8Cg==", "ciphertext": "vault:v1:WAJUPIOn65NV7dI+Zlbcr0z8XJvz1AqYQYJN6+yzGT+CVoKuK3s=" }' \
$VAULT_ADDR/v1/transit/decrypt/my-key2
< HTTP/1.1 400 Bad Request
...
{
"errors": [
"invalid ciphertext: unable to decrypt"
]
}