この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。
皆様こんにちは。
Terraformを利用して、AWSで高可用性アーキテクトの構築をしていきます。
今回はデータベース、ストレージ・ファイルシステムのデータ保護をするためにKMSを作成して暗号化設定をしていきます。
1.高可用性アーキテクト構築目次
2.KMSの概要
AWS Key Management Service (AWS KMS) は、データの保護に使用される暗号化キーの作成と制御を容易にするマネージドサービスです。AWS KMS はハードウェアセキュリティモジュール (HSM) を使用して AWS KMS keys を保護し、FIPS 140-2 暗号化モジュール検証プログラムで検証します。
KMSの主な機能として、鍵管理機能とデータ暗号化機能があります。このうち、データ暗号化機能としては下記3つのAPIがあります。
- Encrypt(データを暗号化)
- Decrypt(データを複合化)
- GenerateDataKey(ユーザーがデータの暗号化に利用するためのカスタマーデータキーを生成)
マスターキーとデータキー
KMSでは、主にマスターキー(CMK)とデータキー(CDK)の2つの鍵を管理します。CMKはデータキーを暗号化するための鍵で、CDKはデータを暗号化するための鍵です。
KMSでは、データキーでデータを暗号化し、データキーをマスターキーで暗号化しています(エンベロープ暗号化)。
類似サービスとしては「CloudHSM」があります。
KMSとCloudHSMの比較は下記の表の通りです。
サービス | CloudHSM | KMS |
---|---|---|
専有性 | VPC内の専有ハードウェアデバイス | AWSが管理するマルチテナント(共有で利用) |
管理場所 | ユーザー側が管理 | AWS側が管理 |
費用 | 高価 | 安価 |
大規模なシステムにはCloudHSMを利用した方がいいでしょう。
3.仕組み図
下記は今回作成するKMSの仕組み図です。
CMKはCustomer Master key、CDKはCustomer Data keyの略称です。
4.KMS作成
全体のソースコードは下記の通りです。
#--------------------------------------
# KMSの作成
#----------------------------------------
resource "aws_kms_key" "higa_WordPress_KMS" {
tags = {
Name = "higa_WordPress_KMS"
}
//ポリシー設定
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:root"
}
Action = "kms:*",
Resource = ["*"]
},
{
Sid = "Allow access for Key Administrators"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:user/CPI-HIGA"
}
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::[アカウントID]:user/CPI-HIGA"
}
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::[アカウントID]:user/CPI-HIGA"
}
Action = [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
]
Resource = ["*"]
Condition = {
Bool = {
"kms:GrantIsForAWSResource" = "true"
}
}
}
]
})
//ここまでポリシー設定のコード
}
#エイリアスの作成
resource "aws_kms_alias" "higa_WordPress_KMS" {
name = "alias/higa_WordPress_KMS"
target_key_id = aws_kms_key.higa_WordPress_KMS.key_id
}
4-1.暗号化鍵の作成
データベース、ストレージ、ファイルシステム等のデータを暗号化するための暗号化鍵の作成をしていきます。(4~7行目)
resource "aws_kms_key" "higa_WordPress_KMS" {
tags = {
Name = "higa_WordPress_KMS"
}
//ポリシーを作成
(以下省略(4-1に記載))
}
上記のコードで暗号化鍵の作成ができます。KMSキーはキーポリシーが必要です。「4-1」で暗号化鍵の設定をしていきます。
キーのタイプについて
キーのタイプには対称鍵と非対称鍵があります。
対称鍵は暗号化と復号化に同じ鍵を使用します。
非対称鍵は暗号化と復号化に別の鍵を使用します。暗号化に使用する鍵は公開鍵と言い、復号に使用する鍵は秘密鍵と言います。
キータイプの設定はcustomer_master_key_spec
オプションで設定します。スペックの選択については、AWSキー管理サービスを参照してください。
customer_master_key_spec
オプションを設定しない場合、デフォルトのキー仕様であるSYMMETRIC_DEFAULTが設定されます。キーは対称鍵仕様です。
「3.仕組み図」より、EBS、RDS、EFSにKMSを使用します。
Amazon EBS は、対称 KMS キーのみをサポートします。非対称 KMS キーを使用して Amazon EBS ボリュームを暗号化することはできません。KMS キーが対称か非対称かを判断する方法については、非対称 KMS キーの識別 を参照してください。
引用元の公式ドキュメントより、EBSは対称KMSのみをサポートするので、今回のKMS作成は対称鍵を選択します。
今回作成するKMSのキー仕様は「SYMMETRIC_DEFAULT」です。
4-2.キーポリシーの設定
暗号化鍵に使用するキーポリシーを下記の通りに作成します。(9~90行目)
//ポリシー設定
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:root"
}
Action = "kms:*",
Resource = ["*"]
},
{
Sid = "Allow access for Key Administrators"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:user/[IAMユーザー]"
}
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::[アカウントID]:user/[IAMユーザー]"
}
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::[アカウントID]:user/CPI-HIG[IAMユーザー]"
}
Action = [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
]
Resource = ["*"]
Condition = {
Bool = {
"kms:GrantIsForAWSResource" = "true"
}
}
}
]
})
//ここまでポリシー設定のコード
ステートメントごとに分割して説明していきます。
Terraformを使用して、JSON形式でポリシードキュメントを記述する際はTerraform 公式ドキュメントを参照してください。
4-2-1
ソースコードは15~23行目に該当します。
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:root"
}
Action = "kms:*",
Resource = ["*"]
},
上記のステートメントではrootユーザに対し、KMSに関する全ての権限を付与しています。
AWSアカウントのrootユーザーは削除することができないため、Sid = "Enable IAM User Permissions"
を設定することで、管理者権限を持つ IAM user、IAM roleを誤って削除してしまってもrootユーザーから操作することができます。
4-2-2
ソースコードは25~48行目に該当します。
{
Sid = "Allow access for Key Administrators"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:user/[IAMユーザー]"
}
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 access for Key Administrators"
で指定のユーザにKMSキーを管理する権限を付与しています。
ユーザーの指定は4~6行目のところで指定します。今回は私のIAMユーザーを指定しています。
上記のステートメントでは、キーの作成、一覧、削除、削除スケジュールの有効化、無効化などを設定しています。
4-2-3
ソースコードは50~65行目に該当します。
{
Sid = "Allow use of the key"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::[アカウントID]:user/[IAMユーザー]"
}
Action = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
Resource = ["*"]
},
上記ステートメントはSid = "Allow use of the key"
で指定のユーザ(私のIAMユーザー)にKMSキーを使用する権限を付与しています。7~13行目のAction
でデータの暗号化、複合化、データキーの生成を許可しています。
4-2-4
ソースコードは68~86行目に該当します。
{
Sid = "Allow attachment of persistent resources"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::【アカウントID】:user/CPI-HIGA"
}
Action = [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
]
Resource = ["*"]
Condition = {
Bool = {
"kms:GrantIsForAWSResource" = "true"
}
}
}
上記ステートメントでは、Sid = "Allow attachment of persistent resources"
でAWSリソースがKMSキーを使用する権限を付与しています。
16行目の"kms:GrantIsForAWSResource" = "true"
でAWSリソースがユーザーに代わって権限を作成し、AWSリソースが KMSキーを使用してユーザーのデータを暗号化できるようになります。
4-3.エイリアスの設定
エイリアスは、AWS KMS key のわかりやすい名前です。例えば、エイリアスを使用すると、1234abcd-12ab-34cd-56ef-1234567890ab の代わりに KMS キーを test-key として参照できます。
引用元:エイリアスの使用
ソースコードは93~97行目に該当します。
#エイリアスの作成
resource "aws_kms_alias" "higa_WordPress_KMS" {
name = "alias/higa_WordPress_KMS"
target_key_id = aws_kms_key.higa_WordPress_KMS.key_id
}
上記でエイリアスの作成ができました。
下記はエイリアスの設定項目です。
使用するオプション | 設定値 | 説明 |
---|---|---|
name | "ailias/【設定したいエイリアス名】" | エイリアスの表示名 |
target_key_id | aws_kms_key.リソース名.key_id | 設定は必須です。エイリアスの対象となるキーの識別子は、ARNまたはkey_idのいずれかです。 |
上記より、マネジメントコンソール画面からKMSの作成、エイリアスの設定が確認できました。
5.まとめ
KMSは抽象的で苦手意識があったので、「暗号化されて安全なんだな~」くらいの認識でした。
この記事でKMSの概要や仕組み図を作成するにあたって、KMSの調査をし、アウトプットすることで理解が深まりました。特に、「CMK」「CDK」「エンベロープ暗号化」「対称鍵・非対称鍵」といった概念はこれまで苦手意識があったので、今回の記事作成を通して理解することができました。
また、TerraformでKMSを作成するにあたり、TerraformでJSON形式でポリシードキュメントを記述する際、JSONの記述と異なる部分(ダブルクォーテーション("")の有無、JSONではコロン(:)で記述しているが、Terraformではイコール(=)で記述している)という発見がありました。
6.参考文献
- terraformの公式ドキュメント
Docs overview | hashicorp/aws | Terraform Registry