SCS受験前に押さえたい!AWS KMS初心者向けハンズオン

AWS

2022.5.12

Topics

はじめに

AWS KMS(Key Management Service)は暗号化/復号に利用する「鍵」を管理するサービスです。AWSの多くのサービスは暗号化機能を有していますが、暗号化に必要な「鍵」は、このKMS上で管理されています。

「管理」とは「鍵を安全に保管し、必要なときに、必要な相手に提供する」ことです。データは暗号化を行うことで保護されますが、暗号化に必要な「鍵」は自分で保護しなければなりません。ファイルとして自分のPCに保存しても良いですが、他のユーザやアプリケーションに鍵を利用させたい場合はどうでしょうか。ファイルとして鍵を渡してしまうと、相手は制限なく利用したり、複製する事が可能となってしまいます。

KMSでは、IAMポリシーによるアクセス許可や、Cloud Trailによる利用履歴のトレースなど、AWSの仕組みを利用した鍵の管理が実現出来ます。また、AWSのサービスだけではなく、独自アプリケーションの暗号化処理で利用することも可能です。

AWSを利用していれば必ず触れることになるIAMとは異なり、KMSは使ったことがないという方も多いのではないでしょうか。AWS Certified Security – Specialty 試験ガイドで示されている通り、AWS Certified Security – Specialty (SCS-C01) の出題範囲にも含まれていますので、受験を考えられている方は、ぜひ一度利用してみてください。

本ハンズオンではKMSを利用した暗号化/復号の流れと、鍵へのアクセス許可に関する仕組みを学習できます。想定時間は1~2時間程度です。あとでと言わずに今すぐチャレンジしましょう!!

想定読者

  • 「S3バケットの作成」「EC2インスタンスの起動」のような基本的なAWS操作が可能な方
  • 特に「AWS Certified Security – Specialty (SCS-C01)」の受験を控えている方

ハンズオンの流れ

  • 1, S3オブジェクトの暗号化
    • KMSを利用して、S3にファイルを暗号化して保存します
    • 保存したファイルをLambdaから復号して中身を読み取ります
  • 2, EBSボリュームの暗号化
    • KMSを利用して、EC2インスタンスのEBSボリュームを暗号化します
    • LambdaからEC2インスタンスの起動を試みます
  • 3, 後片付け
    • キーの削除をスケジュールし、削除保留中の挙動を確認します
    • 作成したリソースを削除します

KMSにおける鍵について

KMSでは複数の「鍵」が登場します。ハンズオンに入る前に、この違いだけ覚えてください。

「CDK」と「CMK」

  • CDK: Customer Data Key (データキー)
    • 実際にデータを暗号化する鍵
    • KMSの内部で都度異なる鍵が自動的に発行される
    • 暗号化/復号処理の中で利用される鍵なので、AWSのサービスで利用する場合は意識せずともOK
  • CMK: Customer Master Key (マスターキー)
    • CDK(データキー)を暗号化する鍵
    • KMSで管理されている「鍵」はこちら
(参考) CMKとCDKを利用した暗号化と復号の流れ


実際の暗号化は以下の流れで行われます。

  1. 利用元サービスがKMSを呼び出し
  2. (KMS) CDKを発行
  3. (KMS) 発行されたCDKをCMKで暗号化
  4. (KMS) 利用元サービスに「平文のCDK」と「暗号化されたCDK」を返却
  5. 利用元サービスが「平文のCDK」を利用して「平文のデータ」を暗号化
  6. 「平文のCDK」と「平文のデータ」を破棄
  7. 「暗号化されたCDK」と「暗号化されたデータ」を保管

復号の流れは以下のとおりです。

  1. 利用元サービスが保管していた「暗号化されたCDK」を取り出してKMSを呼び出し
  2. (KMS) CMKで「暗号化されたCDK」を復号
  3. (KMS) 「平文のCDK」を利用元サービスに返却
  4. 利用元サービスで「平文のCDK」を利用して「暗号化されたデータ」を復号

以上のように、CDKを利用することで、CMK自体はKMSの外に出ない仕組みとなっています。


「AWS マネージド型キー」と「カスタマー管理型のキー」

実際にKMSのマネジメントコンソールを表示すると、メニューに2つの「鍵 (キー)」が存在します。

KMS 鍵の種類

いずれも CMK: Customer Master Key (マスターキー) ですが、管理者が異なります。

  • AWS マネージド型キー (AWS管理CMK)
    • AWS各サービスの暗号化機能で利用されるCMK
    • 「aws/サービス名」として自動的に生成される
    • ユーザ側にも表示されるが、一切の操作は出来ない
    • 3年自動ローテーション
  • カスタマー管理型のキー (カスタマー管理CMK)
    • ユーザが自分で作成/管理するCMK
    • 1年自動ローテーション (ON/OFF可能)

※ この他に「AWS所有CMK」も存在しますが、内部的に利用されるもので、ユーザからは全く見えない存在です。

大変お待たせいたしました。以上がハンズオンの前提となる説明です。
ここからは、実際にKMSを利用した暗号化と復号を体験いただきます。

1, S3オブジェクトの暗号化

KMSで鍵を作る

まずは、暗号化に利用する鍵(カスタマー管理CMK)を作成します。

マネジメントコンソールでAWS KMSを開き、作業を行いたいリージョンを選択します。
「カスタマー管理型のキー > キーの作成」より、キーの作成画面に移ります。

KMS キーの作成

全てデフォルト値でキーを作成します。「エイリアス」は必須のため任意の名前を設定してください。
※ 「キー管理者」や「キーの使用アクセス許可を定義」も、今回は指定せずに作成します。

KMS キーの作成 (エイリアス設定)
KMS キーの作成 (確認)
KMS キー作成後

S3バケットを作成

暗号化したファイルを保存するS3バケットを作成します。
マネジメントコンソールでS3を開き「バケット > バケットを作成」より、バケット作成画面に移ります。

S3 バケット一覧

「バケット名」は任意の名前、「AWS リージョン」は鍵を作成したリージョンを選択します。

S3 バケット作成

「デフォルトの暗号化」で以下の通り作成した鍵を指定します。
※ 本ハンズオンではバケットキーは「無効にする」を選択してください。(挙動をわかりやすくする為)

S3 デフォルトの暗号化

S3 バケット作成成功

S3の暗号化はオブジェクト単位で設定可能ですが「デフォルトの暗号化」を指定することで、都度設定せずともオブジェクトが暗号化されるようになります。

S3バケットにファイルをアップロード

テスト用に、手元のPCで好きな内容のテキストファイルを作成してください。

メモ帳 テストファイル

作成したS3バケットを開き「アップロード」から作成したテキストファイルをアップロードします。
設定は全てデフォルト値で問題ありません。

S3 アップロード

アップロードされたファイルの「サーバー側の暗号化設定」を確認すると、KMSの鍵によって暗号化されていることが分かります。

S3 アップロードしたファイルの暗号化

この場合も「開く」ボタンから、ファイルの中身を表示することが可能です。
この際、裏側ではKMSによる復号処理が行われていますが、ユーザ側からは特に意識されません。

S3 アップロードしたファイル

Lambda関数を作成

では、暗号化されたファイルを他のAWSサービスから利用する場合はどうでしょうか。
今回はS3にアップロードしたファイルを読み取るLambda関数を作成します。

マネジメントコンソールでLambdaを開き、鍵を作成したリージョンを選択します。
「関数 > 関数の作成」からLambda関数を作成します。関数名に任意の名前を指定し、その他はデフォルト値で問題ありません。

Lambda 関数作成

※ 「実行ロール」が「基本的なLambdaアクセス権限で新しいロールを作成」となっていることを確認します。

作成したLambda関数の「コードソース」に以下を貼り付けます。
【リージョン】【S3バケット名】【テストファイル名】は自分で用意した内容に置き換えてください。

const aws = require('aws-sdk')
const s3 = new aws.S3({'region':'【リージョン】'})

exports.handler = async (event) => {
    const data = await s3.getObject({
        Bucket:'【S3バケット名】',
        Key:'【テストファイル名】'
    }).promise()
    
    return {statusCode: 200, body: data.Body.toString()}
}

Lambda コードソース

Lambda関数を実行

作成したLambda関数を実行します。

「Test > Configure test event」より、テストイベントを設定を作成します。
デフォルト値のまま、任意のイベント名を指定してください。

Lambda テスト作成

Lambda テスト作成

「Deploy」ボタンで編集内容をデプロイし、デプロイが正常に完了してから「Test」ボタンでLambda関数を実行します。

Lambda デプロイ

Lambda デプロイ成功

現時点ではS3へのアクセスを許可していない為、「AccessDenied」となり失敗します。

  "errorType": "AccessDenied",
  "errorMessage": "Access Denied",

Lambda S3許可不足で失敗

Lambda関数のIAM Roleに許可を追加

Lambda関数のIAM Roleを編集し、S3へのアクセスを許可します。

Lambda関数の「設定 > アクセス権限 > 実行ロール」のロール名を開きます。

Lambda 実行ロール

IAM Roleの編集画面となるので「アクセス許可を追加 > インラインポリシーを作成」よりポリシーの作成画面に移ります。

Lambda IAMRole インラインポリシーを作成

サービス S3」「アクション 読み込み GetObject」「リソース arn:aws:s3:::【バケット名】/*」を追加します。

Lambda IAMRole S3許可ポリシー

※ 作成されるインラインポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::kms-handson-bucket/*"
        }
    ]
}

再びLambda関数を「Test」ボタンで実行すると、以下の通りエラー内容が変化します。

  "errorType": "AccessDenied",
  "errorMessage": "The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.",

これは、S3へのアクセスは許可されているものの、KMSの許可を受けていない為、鍵が利用できず、復号が出来ていない状況です。

KMSで暗号化されたリソースを使用する場合、対象サービスに加えてKMSを使用する許可も必要なのがポイントです。

IAM Roleを修正

先程IAM Roleに追加したインラインポリシーを「編集」します。

IAM role インラインポリシーの編集

「さらにアクセス許可を追加する」から「サービス KMS」「アクション 書き込み Decrypt」「リソース 【作成した鍵のARN】」を許可します。

Lambda IAMRole KMS許可ポリシー

※ 編集後のインラインポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:ap-northeast-3:【AWSアカウントID】:key/82334b0b-b1f4-47df-8fc7-0ee63d16d5c8",
                "arn:aws:s3:::kms-handson-bucket/*"
            ]
        }
    ]
}

改めてLambda関数を実行すると、KMSによる復号が行われ「Response」内にテストファイルの中身が表示されるはずです!👏👏👏

Lambda 実行成功

(補足1) キーポリシーについて

先程はIAMポリシーによりLambda関数に鍵の利用許可を与えました。KMSにはIAMとは別に「キーポリシー」が存在しており、こちらを利用して許可を与えることも可能です。

マネジメントコンソールから「KMS > 作成した鍵」を開き、「キーポリシー」の「ポリシービューへの切り替え」ボタンをクリックします。デフォルトでは以下のようなキーポリシーが設定されています。

{
    "Id": "key-consolepolicy-3",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【AWSアカウントID】:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        }
    ]
}

「Principal」がキーの利用を許可する対象で、以下のように指定可能です。

  • 「arn:aws:iam::【AWSアカウントID】:root」
  • 「arn:aws:iam::【AWSアカウントID】:user/【IAMユーザ名】」
  • 「arn:aws:iam::【AWSアカウントID】:role/【IAMロール名】」 (又は service-role)

「arn:aws:iam::【AWSアカウントID】:root」は、対象AWSアカウントのrootユーザに対する許可……ではなく、対象AWSアカウントのうち、IAMによってKMSの利用が許可された対象に、鍵の利用を許可します。 つまり、IAMに許可を委ねる指定となります。

「arn:aws:iam::【AWSアカウントID】:user/【IAMユーザ名】」や「arn:aws:iam::【AWSアカウントID】:role/【IAMロール名】」は、IAMに関わらず、KMSのキーポリシーとして鍵の利用を許可します。IAMによる許可は必要ありません。 ※ただし、IAMによって明示的に拒否されている場合は利用できません。

興味のある方は、先程追加したインラインポリシーの「kms:Decrypt」許可を削除し、代わりにキーポリシーに「arn:aws:iam::【AWSアカウントID】:role/service-role/【Lambda関数の実行ロール名】」が「kms:Decrypt」を行う許可を追加してみましょう。

※ キーポリシーへの追加例

{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【AWSアカウントID】:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Lambda",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【AWSアカウントID】:role/service-role/【Lambda関数の実行ロール名】"
            },
            "Action": "kms:Decrypt",
            "Resource": "*"
        }
    ]
}

IAMで明示的に許可されていなくても、Lambda関数から鍵が利用できることが確認できます。

※ さらに、インラインポリシーに「kms:Decrypt」の明示的な拒否を追加すると、キーポリシーで許可されていても、Lambdaの実行が失敗することが確認できます (以下、明示的な拒否の例)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::kms-handson-bucket/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Deny",
            "Action":  "kms:Decrypt",
            "Resource": "arn:aws:kms:ap-northeast-3:【AWSアカウントID】:key/82334b0b-b1f4-47df-8fc7-0ee63d16d5c8"
        }
    ]
}

※ IAMポリシーの反映には若干の遅延があります。意図しない場合は1~2分待ってから再度試してください。

(補足2) 「AWS マネージド型キー」の場合

KMSの鍵、CMKには「AWS マネージド型キー」と「カスタマー管理型のキー」があると説明しました。今回S3の暗号化に使用したのは「カスタマー管理型のキー」です。では「AWS マネージド型キー」とは何でしょうか。

先程作成したS3バケットに、もう一つ違うテキストファイルをアップロードします。この際に「サーバー側の暗号化」で「暗号化設定 デフォルトの暗号化バケット設定を上書きする」「暗号化キータイプ SSE-KMS」「AWS KMS キー AWS 管理キー (aws/s3)」を選択し、バケットの設定を無視して「AWS マネージド型キー」を利用させます。

S3 暗号化

Lambda関数のコードソースを編集し、ファイル名部分を今アップロードしたテキストファイルに変更します。

Lambda ファイル名変更

「Deploy」→「Test」でLambda関数を実行すると、今回は鍵へのアクセス許可を設定していないにも関わらず、問題なくファイルが復号され読み取れます。

Lambda 実行結果

これは何故でしょうか。答えは「AWS マネージド型キー」のキーポリシーにあります。

マネジメントコンソールから「KMS > AWS マネージド型キー」を開くと「aws/s3」という鍵が存在します。
※ 対象リージョンで各種サービスからAWS管理キーを使用すると、自動的に生成されます。

KMS マネージド型キー

AWS管理の鍵であるため、ユーザは一切の操作が出来ませんが、キーポリシーを確認することは可能で、以下のような内容になっています。

{
    "Version": "2012-10-17",
    "Id": "auto-s3-2",
    "Statement": [
        {
            "Sid": "Allow access through S3 for all principals in the account that are authorized to use S3",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "kms:ViaService": "s3.ap-northeast-3.amazonaws.com",
                    "kms:CallerAccount": "【AWSアカウントID】"
                }
            }
        },
        {
            "Sid": "Allow direct access to key metadata to the account",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【AWSアカウントID】:root"
            },
            "Action": [
                "kms:Describe*",
                "kms:Get*",
                "kms:List*"
            ],
            "Resource": "*"
        }
    ]
}

着目すべきは「”kms:ViaService”: “s3.ap-northeast-3.amazonaws.com”」と「”kms:CallerAccount”: “【AWSアカウントID】”」です。これは、同じAWSアカウントから、対象のサービスで利用する場合のみ、鍵の利用を許可する設定となっています。つまり、同じAWSアカウントのLambda等からS3で鍵を使用するケースは許可されているということです。

一方で、S3のバケットポリシー等でPublicアクセスを許可した場合「同じAWSアカウントからの利用」ではなくなる為、KMSの鍵が利用できず、オブジェクトを復号できません。

2, EBSボリュームの暗号化

続いて、同じ鍵を利用してEC2インスタンスのストレージであるEBSボリュームの暗号化を行います。

EC2インスタンスの作成とEBSボリュームの暗号化

まずは対象となるEC2インスタンスとEBSボリュームを作成します。

マネジメントコンソールからEC2を開き、鍵を作成したリージョンを選択します。
「インスタンス > インスタンスを起動」に進み、以下の通り設定してください。
※ 今回はEC2インスタンスへのログインや通信は行わない為、細かい設定は任意です。

  • 名前 任意の名前
  • OSイメージ AmazonLinux (又は任意)
  • インスタンスタイプ 任意 (t2.microやt3.nano等)
  • キーペア キーペアなしで続行
  • ネットワーク設定 デフォルト (又は任意)
  • ストレージを設定
    • 「アドバンスト」をクリックし、詳細設定を表示します
    • 「ボリューム 1 (AMIルート)」に対し「暗号化済み Yes」「KMS キー 初めに作成した鍵」を選択します
      ※ 「(デフォルト) aws/ebs」は利用しない

EBS 暗号化

EC2インスタンスが問題なく起動したら、一度停止してください。

EC2 インスタンス停止

LambdaからEC2インスタンスを起動

EBSボリュームが暗号化されている場合、EC2インスタンスを起動する際に、KMSを利用して復号する権限が必要です。この動作を確認するために、S3と同様にLambda関数からEC2インスタンスの起動を試みます。

マネジメントコンソールでLambdaを開き、鍵を作成したリージョンを選択します。
「関数 > 関数の作成」からLambda関数を作成します。関数名に任意の名前を指定し、その他はデフォルト値で問題ありません。

作成したLambda関数の「コードソース」に以下を貼り付けます。
【リージョン】【EC2インスタンスID】は自分で用意した内容に置き換えてください。

const aws = require('aws-sdk')
const ec2 = new aws.EC2({'region':'【リージョン】'})

exports.handler = async (event) => {
    const data = await ec2.startInstances({
        InstanceIds: ['【EC2インスタンスID】']
    }).promise()
    
    return {statusCode: 200, body: data}
}

Lambda EC2起動関数

「Test > Configure test event」からテストを作成し、「Deploy」→「Test」でLambda関数を実行します。

まだIAMRoleで何も許可していないため、権限不足で失敗します。

  "errorType": "UnauthorizedOperation",
  "errorMessage": "You are not authorized to perform this operation. Encoded authorization failure message: 1dy1SF4GlRj08f4KL6j2HmBXQLlFGdQMveDE0BWufNLUoYX5DqUa9Wd2yOfycafrox7M60CHEaQAWLCl0_Ph03aKufHPGbR3VNVPaXjzwWO_f_k1yRQadlPnUvSUC68ngVMcl14JlqGGdneHkRSUB0s1Nfs8ZJoLwtMPHnRBEFTumEUYhswKvE89DwnUMB46EXJ0BUYKzU1X2qTOIDpeRNiVCCIIXBRzx7Bxg9qs0ih7knuYogxNs7wdgutXOyDSgntaz-sFDvkwtvE-DGmPG9N6w5Xj_Z6A2li595o1m2cijFbKINPQb07aiQWYyny3_9jh7-3zFSRs8FQeabrKSif-87DuwEGXaBg5ZsOoR4lJ4II-wKBzc_rzhCDvaDlf-UPWL1A_WYJcvtY6qVSlB6O6J9Iol0MITwJt4fxWH6d2sMknH5LIZzcxdye_ulk2lez0QnCY46kDhzOY9QZFxP3XNR9yHBFHHk7hnDW3Bn3vkTCdBDxH8NzDIusFkcwvERqAAb6KxGxdP2MVt_o7MSML8q3rv7G2aitJi_bt--l6rnPXIOT56DaDHGt46Qcm4XdL7Ew6A-4viWbP3ceJ-W0DsGc5xmRVfi106mYCDM4_db8FqMCL68VLYyPSJguUJqMht7s2rB4OUiYFvRrqAdqSAvZtceXfTsZgJO0hq21pxo8sissrOH34t0p3M5T47aLHun5BIQ51BEXEXBWHZPs",

では、先程同様に実行ロールにEC2インスタンスの起動と、KMSのDecryptを許可します。
「設定 > アクセス権限 > 実行ロール」のロール名を開き、「アクセス許可を追加 > インラインポリシーを作成」と進み、以下を許可します。

  • サービス EC2」「アクション 書き込み StartInstances」「リソース 【EC2インスタンスのARN】」
  • サービス KMS」「アクション 書き込み Decrypt」「リソース 【作成した鍵のARN】」

IAM role EC2とKMS許可

ポリシーに任意の名前を付けて保存した後、再度「Deploy」→「Test」でLambda関数を実行すると、成功したような結果が得られます。

Lambda関数 実行結果

しかし、EC2インスタンスを確認すると「停止済み」のまま変化していないはずです。これは何故でしょうか。CloudTrailを確認すると、その答えが分かります。

CloudTrailのイベント履歴を確認

マネジメントコンソールからCloudTrailを開き、鍵を作成したリージョンを選択します。

「イベント履歴」から、Lambda関数を実行した時刻のログを確認すると、EC2の「StartInstances」の直後に、KMSの「CreateGrant」が実行されています。

CloudTrail イベント履歴

イベントの詳細をみると、以下のように権限不足により失敗していることが分かります。

    "errorCode": "AccessDenied",
    "errorMessage": "User: arn:aws:sts::【AWSアカウントID】:assumed-role/kms-handson-func-ec2-role-9n3s60z7/kms-handson-func-ec2 is not authorized to perform: kms:CreateGrant on resource: arn:aws:kms:ap-northeast-3:【AWSアカウントID】:key/82334b0b-b1f4-47df-8fc7-0ee63d16d5c8 because no identity-based policy allows the kms:CreateGrant action",

S3の場合はKMSの「Decrypt」が実行されていましたが、EC2+EBSの場合は「CreateGrant」が実行されているということになります。

「Grant (権限)」とは

では、この「Grant」とは何でしょうか。AWSの日本語ドキュメントでは「権限」と訳されている場合があります。

これはKMSの鍵を、一時的に他のサービスに利用させるための仕組みです。通常はキーポリシーやIAMポリシーによって許可されているサービスしか鍵を利用することは出来ませんが、「Grant」により権限が与えられたサービスは一時的に鍵を利用することが出来ます。

今回暗号化を行っているのはEC2ではなくEBSである為、EBSが鍵を利用出来る必要があります。アタッチされたEBSボリュームが暗号化されている場合、EC2はインスタンス起動時に「CreateGrant」によってEBSに鍵の利用を許可しています。Lambdaから実行する場合、この「CreateGrant」を許可する必要があります。

IAM Roleを修正

先程編集したIAM Roleのインラインポリシーを編集し、以下を許可します。 ※Decryptは不要

  • サービス EC2」「アクション 書き込み StartInstances」「リソース 【EC2インスタンスのARN】」
  • サービス KMS」「アクション 書き込み アクセス権限の管理 CreateGrant」「リソース 【作成した鍵のARN】」「リクエスト条件 kms:GrantIsForAWSResource (Bool true)」

※ EC2インスタンスのARN: 「arn:aws:ec2:【リージョン】:【AWSアカウントID】:instance/【EC2のインスタンスID】」
※「kms:GrantIsForAWSResource」は、AWSのリソースから求められた場合にのみ許可する指定です

IAM リクエスト条件

※ 編集後のインラインポリシー例

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:StartInstances",
            "Resource": "arn:aws:ec2:ap-northeast-3:【AWSアカウントID】:instance/i-064fc73454d200cd8"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "kms:CreateGrant",
            "Resource": "arn:aws:kms:ap-northeast-3:【AWSアカウントID】:key/82334b0b-b1f4-47df-8fc7-0ee63d16d5c8",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}

改めてLambda関数を実行すると、今後は問題なくEC2インスタンスが起動できているはずです。👏👏👏

EC2インスタンス 起動

お疲れ様でした!以上でハンズオンは終了です。ここからリソースの削除に移ります。

3, 後片付け

鍵の削除

マネジメントコンソールから「KMS > カスタマー管理型のキー」を開き、作成した鍵を選択します。「キーのアクション > キーの削除をスケジュール」に進み、確認にチェックを付けて「削除をスケジュール」します。
※ KMSの鍵(CMK)を削除すると、鍵によって暗号化されたデータは絶対に復号出来なくなります。 安全のため、鍵の削除には待機期間が設定されており、7~30日で選択可能ですが、0日にすることは出来ません。

KMS キーの削除をスケジュール

スケジュール後、ステータスが「削除保留中」となっていれば問題ありません。

この状態で既に鍵は利用できなくなっており、初めにS3に暗号化して保存したテキストファイルをブラウザで開こうとすると、以下のようにエラーとなります。

<Error>
<Code>KMS.KMSInvalidStateException</Code>
<Message>arn:aws:kms:ap-northeast-3:【AWSアカウントID】:key/82334b0b-b1f4-47df-8fc7-0ee63d16d5c8 is pending deletion.</Message>
<RequestId>YKNHTY15FPK60A10</RequestId>
<HostId>A/8pAkFnvs6HxOVi7mGNBo86FZoF3AjCoTDqS6ea7vIDV5q9BNklxiW2efZWqeaQkqvQR+KOHds=</HostId>
</Error>

この試行はCloudTrailにイベントとして記録されるため、実運用で鍵を削除する場合は、待機期間中に鍵の利用試行が発生していないか監視すると良いでしょう。必要な場合は待機期間中に「キーの削除をキャンセル」し「有効」化することで、元通り鍵が利用可能となります。

各種リソースの削除

ハンズオンで作成した以下のリソースを削除してください。

  • EC2インスタンス (及びEBSボリューム)
  • S3バケット
  • IAM Role (Lambda関数の実行ロール x2)
  • Lambda関数 (x2)
  • CloudWatch ロググループ 「/aws/lambda/【Lambda関数名】」 (自動的に作成されます)

さいごに

今回はKMSをAWSの各サービスから利用する流れを体験いただきました。座学的に学習すると分かり辛い部分なので、このハンズオンが理解の助けになっていれば幸いです。

KMSを構成する要素は他にも沢山あります。例えば「カスタマー管理型のキー」を作成する場合に「キーマテリアルオリジン」という選択項目が存在しますが、これは鍵の実体(キーマテリアル)をどのように生成・保管するか指定する項目です。今回はデフォルト値である「KMS」を選択し、KMS内で自動的に生成・保管させましたが、「外部」を選択するとユーザが自分で鍵を作成し、KMSに持ち込む(キーマテリアルのインポート)事が可能です。いくつかメリットと制約事項が存在し、例えばKMSが生成したキーマテリアルは待機期間を経ないと削除出来ませんが、インポートしたキーマテリアルはいつでも削除することが可能です。

KMSをより深く理解したい方は「キーマテリアルのインポートを試してみる」「鍵をローテーションさせる方法を確認する」「AWSのサービスではなく、自分のアプリケーションやAWS CLI等からKMSを利用した暗号化/復号を行ってみる」「他のAWSアカウントに鍵の利用を許可してみる」などのお題にチャレンジしてみてください。

sdat

2015年新卒入社。サーバエンジニアとして長らく運用現場を見てきましたが、クラウドマイグレーションのチームを任されるに至りました。初めてのPCはVineLinux、趣味で触るのはJavaScript。物事を手持ちの札で解決できたときが一番楽しい。最強になりたい。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら