明けましておめとうございます!
今年もADACHIN SERVER LABOを
よろしくお願いします!
というわけで2021年初のブログということですが、最近私はPS4のゲームが飽きて、PS3/PS2にハマっています。昔のゲームってエモいわ…
去年の振り返りブログは書かないの?とツッコミを入れたいところですが、気が向いたら書くという感じで、今回はAWS KMS(Key Management Service)を触ってみたので、そこらへんのノウハウを紹介したいと思います。
AWS KMSとは?
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/overview.html
AWS Key Management Service (AWS KMS) は、データの暗号化に使用される暗号化キー カスタマーマスターキー (CMKs) の作成と管理を容易にするマネージド型サービスです。AWS KMS は、データを暗号化する他のほとんどの AWS のサービスと統合されています。AWS KMS は、AWS CloudTrail とも統合されており、監査、規制、コンプライアンスのニーズに応じて CMKs の使用をログに記録します。
簡単に言うとDBのパスやらクレデンシャルなどの機密情報などをサーバーで管理してしまうと雑多になってしまうし、不正アクセスされて流出されたら終了です。そのためにAWS KMSを利用することで、万が一、流出されてしまっても、キーを暗号化することで解読不能にしてトレースできるのがベストです。インフラやっている人はHashicorpのVaultかな!と思うかもしれませんが、まさにそれです。以下概念見ていきましょう。
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/concepts.html
簡単に図書いてみましたが、カスタマーマスターキー(CMKs)から既存のKeyを暗号化して、復号化すればいいので、既存のKeyはいくら削除してもAWS KMSに残り続けます。それと暗号されているKeyは管理しないといけないので、S3にバックアップしておけばOKですね。次にTerraformでAWS KMSを自動化してみます。
Resource: aws_kms_key
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key
まずはIAMユーザーのポリシーに AWSKeyManagementServicePowerUser
を付け加えましょう。
- kms.tf
1 2 3 4 5 6 7 8 9 10 11 12 |
resource "aws_kms_key" "adachin" { description = "Master Key adachin" enable_key_rotation = true is_enabled = true deletion_window_in_days = 30 policy = file("files/assume_role_policy/kms.json") } resource "aws_kms_alias" "adachin" { name = "alias/adachin" target_key_id = aws_kms_key.adachin.key_id } |
- files/assume_role_policy/kms.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
{ "Id": "key-consolepolicy-3", "Version": "2012-10-17", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxx:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxx:user/administrator" }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:TagResource", "kms:UntagResource", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxx:user/kms" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }, { "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxxxxxxxx:user/kms" }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } } } ] } |
Terraform化は至って簡単で、上記のポリシーはadministratorが30日後に完全削除するようにして、仮で作成したkmsユーザーでポリシーの変更や鍵の利用をできるようにしました。 xxxxxxxxx
の部分はAWSアカウント番号になるので適宜変更してください。作成したらまず動作確認としてテストしてみましょう。
KMS test
- CMKsの確認
1 2 3 4 5 6 7 8 9 |
$ aws kms list-keys { "Keys": [ { "KeyArn": "arn:aws:kms:ap-northeast-1:xxxxxxxxx:key/xxxxxxxxxxxxxxxxxxxxxxxx", "KeyId": "xxxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxx" } ] } |
- aliasで調べる
1 2 3 4 5 6 |
$ aws kms list-aliases | jq '.Aliases[] | select( .AliasName | test("adachin"))' { "AliasArn": "arn:aws:kms:ap-northeast-1:xxxxxxxxx:alias/adachin", "AliasName": "alias/adachin", "TargetKeyId": "xxxxxxxxx-xxxxxxx-xxxx-xxxx-xxxxxxxx" } |
- 暗号化する(Encrypt)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ ls test.key $ cat test.key test $ aws kms encrypt \ --key-id alias/adachin \ --plaintext fileb://test.key \ --output text \ --query CiphertextBlob \ | base64 --decode > encrypt-test.key $ ls test.key encrypt-test.key $ cat encrypt-test.key x|ba 00Rdgd0MeBb`cdvfhdhHe.0 Y} idgdfbdbdf9P%d- z=ErE9~84H*(P $ rm test.key |
- 復号化する(Decrypt)
1 2 3 4 5 6 7 8 9 10 11 |
$ aws kms decrypt \ --ciphertext-blob fileb://encrypt-test.key \ --output text \ --query Plaintext \ | base64 --decode > test.key $ ls test.key encrypt-test.key $ cat test.key test |
ちゃんと復号化されていればOKです!
次はタイトルに書いてある通り!GCPのサービスアカウントで鍵(クレデンシャル)を暗号化して、Digdagでどう復号化してEmbulkでシンクするのか作ってみました。
Digdagの場合
- decrypt.sh
1 2 |
#!/bin/sh aws kms decrypt --ciphertext-blob fileb://~/.gcp/big-encrypt.key --output text --query Plaintext | base64 -d > /digdag/bigquery/config/bigquery.key |
- test.dig
1 2 3 4 5 6 7 8 9 10 11 12 |
$ cat test.dig _error: sh>: /digdag/bigquery/post_slack.sh "[${session_time}][${session_id}] DigDag Fail test" +decrypt: sh>: /digdag/bigquery/decrypt.sh +actions: sh>: export $(cat config/env | xargs) && /usr/local/bin/embulk run -b $EMBULK_BUNDLE_PATH embulk/test.yml.liquid +delete-key: sh>: rm -rf /digdag/bigquery/config/bigquery.key |
まず復号化をするためのシェルスクリプトを配置します。test.digでは復号化してからembulkでシンクし、その後 復号化された鍵を削除します。これでDigdagが動いている時だけサーバー上に存在することになりますが、さらにセキュアにするならdigdag.env.storeの変数に格納してサーバーに残らないようにするようにすれば尚良し!これは後で実装してみよう。
まとめ
わざわざ手動でサーバー入って鍵の配布やらクレデンシャルを管理しなくていいのと、KMS1本で操作できるのでめちゃくちゃ便利だということがわかりました。コンテナ運用でも.envとかS3からコピーするのではなく、KMSから復号化して設置するほうがセキュアですね。S3で知らずに公開!「げ、クレデンシャル書いてる!まずい!」などはしないだろうけど暗号化して担保したほうが良さそう。
ドキュメント読むより実際に触って試してみるといいです!
0件のコメント