はじめに
非公開エクスポートは保存前に暗号化する必要があります。小さな合成ファイルを暗号化し、1 つの読み取り担当に元のバイト列を復元させ、復号の失敗を診断して、キーの削除をスケジュールします。
先に LabEx で AWS を使い始める、レポートの読み取り役に最小権限を与える、IAM ロールで一時認証情報を使う を完了してください。この新しい VM は、独自のファイル、読み取りロールのセッション、参照キーを提供します。
認定試験との関連
このラボでは、次の試験トピックに関連する実践的な演習を行います。
- Cloud Practitioner (CLF-C02) · タスク 2.2: KMS の暗号化、復号権限、キーの状態。
- Solutions Architect – Associate (SAA-C03) · タスク 1.3: KMS の暗号化、復号権限、キーの状態。
- Developer – Associate (DVA-C02) · タスク 2.2: KMS の暗号化、復号権限、キーの状態。
- CloudOps Engineer – Associate (SOA-C03) · タスク 4.2: KMS の暗号化、復号権限、キーの状態。
- Security – Specialty (SCS-C03) · タスク 5.3: 基礎演習:KMS の暗号化、復号権限、キーの状態。
- Data Engineer – Associate (DEA-C01) · タスク 4.3: 基礎演習:KMS の暗号化、復号権限、キーの状態。
- DevOps Engineer – Professional (DOP-C02) · タスク 6.2: 基礎演習:KMS の暗号化、復号権限、キーの状態。
- Solutions Architect – Professional (SAP-C02) · タスク 2.3: 基礎演習:KMS の暗号化、復号権限、キーの状態。
非公開エクスポートを暗号化する
このステップでは、AWS Key Management Service(KMS) のキーを作成し、提供されたエクスポートを暗号文に変換します。個人データの代わりに、提供された合成データ private-export.json を使ってください。export-reader プロファイルは、準備済みの読み取りロールの一時セッションを使います。最初は KMS 権限がありません。alias/labex-sec01-reference を保持してください。
Terminal の隣で AWS View を開き、キーの状態、読み取り担当への権限付与、暗号処理リクエストの結果を比較します。バイト列のハッシュを使うことで、非公開データを表示せずに結果を比較できます。
対称キーは、暗号化と復号に同じ保護されたキー素材を使います。KMS はそのキー素材をサービス内に保持します。エイリアスはキーに読みやすい名前を付けますが、一意のキー ARN を置き換えるものではありません。
提供されたプロジェクトディレクトリから始めます。cd は現在のディレクトリを変更します。呼び出し元のクエリは、認証情報を表示せずに、準備済みの操作担当者の識別情報を確認します。
cd /home/labex/project
aws sts get-caller-identity --query Arn --output text
labex-sec01-operator ユーザーの ARN が返るはずです。自分のキーを作成します。--query はレスポンスから 1 つのフィールドを選択し、--output text は JSON の引用符を取り除きます。$(...) は後続のコマンドで使うために、その結果をシェル変数へ保存します。
KEY_ARN=$(aws kms create-key --description labex-sec01-owned-export --query KeyMetadata.Arn --output text)
aws kms create-alias --alias-name alias/labex-sec01-private-export --target-key-id "$KEY_ARN"
aws kms describe-key --key-id "$KEY_ARN" --query 'KeyMetadata.[KeyState,KeySpec]' --output text
Enabled と SYMMETRIC_DEFAULT が返るはずです。参照キーを使用したり変更したりしないでください。

公式コンソールの参考画像:エイリアス、Enabled 状態、ARN は、先ほどクエリしたキーの識別情報と状態に対応します。画像は AWS の例の値です。Terminal では引き続き自分の KEY_ARN を使ってください。
出典:AWS KMS。
暗号化コンテキストは、暗号文に結び付けられた秘密ではないラベルの集合です。復号では同じラベルを指定する必要があります。ここでは Purpose=private-export が、このエクスポートの意図する用途を示します。コンテキスト値にパスワードや個人データを入れないでください。
KMS Encrypt は小さな平文を扱います。この準備済みエクスポートは 4 KiB の上限を十分に下回ります。fileb:// は入力をバイナリのバイト列として読み取ります。CLI は返された暗号文を base64 で表し、base64 --decode はそれをバイナリファイルに戻します。パイプは出力を次のコマンドへ送り、> は結果を指定されたファイルに書き込みます。
aws kms encrypt --key-id "$KEY_ARN" --plaintext fileb://private-export.json --encryption-context Purpose=private-export --query CiphertextBlob --output text | base64 --decode > private-export.kms
sha256sum でバイト列のハッシュを比較します。異なるハッシュは、暗号文が元のデータと異なることを示します。これだけでは権限の証拠になりません。
sha256sum private-export.json private-export.kms
AWS View を開きます。Customer key inventory に有効な自分のキーが表示され、Cryptographic requests に、入力がエクスポートと一致する、許可された操作担当者の Encrypt リクエストが表示されるはずです。
1 つの読み取りロールにアクセスを許可する
このステップでは、アプリケーションの読み取り担当がエクスポートキーだけで復号できるようにします。IAM ロールの権限は、アクションとその適用対象リソースの両方を指定します。kms:Decrypt はバイト列の復元を許可しますが、暗号化やキーの管理は許可しません。

読み取り担当がエクスポートを復元するには、正しいコンテキスト、Decrypt の権限付与、有効なキーが必要です。
まず、権限を付与する前に読み取り担当のプロファイルを試します。--profile export-reader は、操作担当者の代わりに、準備済みの一時ロールセッションを選択します。コマンドはアクセス拒否のレスポンスで失敗し、平文を返さないはずです。
aws kms decrypt --profile export-reader --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=private-export --query KeyId --output text
ポリシードキュメントを作成します。ヒアドキュメントは <<EOF と EOF の間の行を read-export.json に書き込みます。シェルは $KEY_ARN を正確なキー ARN に展開します。この権限付与には、ワイルドカードのアクションもワイルドカードのリソースも使いません。
cat > read-export.json <<EOF
{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Action": "kms:Decrypt", "Resource": "$KEY_ARN"}]
}
EOF
このインラインポリシーを読み取りロールへアタッチします。インラインポリシーはこのロールに属し、後片付けの際に個別に削除できます。提供されたキーは、標準の同一アカウント用キーポリシーを使っています。このポリシーによって、IAM 権限でこのロールを認可できます。
aws iam put-role-policy --role-name labex-sec01-export-reader --policy-name ReadPrivateExport --policy-document file://read-export.json
読み取り担当のセッションで、暗号化されたバイト列を復元します。コマンドは base64 の平文フィールドを選択してデコードし、内容を表示せずに復元されたエクスポートを書き込みます。
aws kms decrypt --profile export-reader --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=private-export --query Plaintext --output text | base64 --decode > restored-export.json
cmp は実際のファイルのバイト列を比較します。&& により、比較が成功したときだけメッセージが表示されます。
cmp private-export.json restored-export.json && echo "Original export bytes recovered"
Original export bytes recovered が表示されるはずです。AWS View には、正確なキーを対象にした読み取りポリシーと、復元されたバイト列がエクスポートと一致する、許可された読み取りロールの Decrypt が表示されるはずです。このロールの権限を、自分のキーに対する Decrypt に限定してください。

3 種類の復号失敗を診断する
このステップでは、コンテキスト、権限、キー状態による失敗を区別します。それぞれの結果の原因が明確になるように、同じ暗号文を使い続けてください。以下の失敗を確認するコマンドは、意図的にキー識別子だけを選択し、平文を選択しません。
最初にコンテキスト値だけを変更します。権限がある読み取り担当でも、誤ったコンテキストでは暗号文を復号できません。
aws kms decrypt --profile export-reader --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=wrong-context --query KeyId --output text
InvalidCiphertextException が返るはずです。キーとロールへの権限付与は引き続き存在しますが、コンテキストが Encrypt で使ったものと一致しません。
次に、ロールへの権限付与を削除し、正しいコンテキストのリクエストを繰り返します。インラインポリシーの削除は、キーや暗号文を変更せずに認可を変更します。
aws iam delete-role-policy --role-name labex-sec01-export-reader --policy-name ReadPrivateExport
aws kms decrypt --profile export-reader --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=private-export --query KeyId --output text
アクセス拒否のレスポンスが返るはずです。次のテストの前に、範囲を限定した権限付与を復元します。
aws iam put-role-policy --role-name labex-sec01-export-reader --policy-name ReadPrivateExport --policy-document file://read-export.json
最後にキーを無効にします。無効なキーは一覧に残りますが、暗号処理を実行できません。キー状態による失敗だけを確認するため、権限を持つ操作担当者のプロファイルを使います。
aws kms disable-key --key-id "$KEY_ARN"
aws kms decrypt --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=private-export --query KeyId --output text
DisabledException が返るはずです。キーを有効にし、成功する読み取り担当の復元を繰り返して、通常の動作に戻ったことを確認します。
aws kms enable-key --key-id "$KEY_ARN"
aws kms decrypt --profile export-reader --key-id "$KEY_ARN" --ciphertext-blob fileb://private-export.kms --encryption-context Purpose=private-export --query Plaintext --output text | base64 --decode > restored-export.json
cmp private-export.json restored-export.json && echo "Reader access restored"
AWS View の Cryptographic requests テーブルを確認します。拒否されたリクエストの呼び出し元、コンテキスト、結果を比較してください。ロールへの権限付与では、コンテキストの不一致や無効なキーを修復できません。

所有するキーを安全に廃止する
このステップでは、読み取り担当への権限付与とエイリアスを削除し、自分のエクスポートキーだけの削除をスケジュールします。KMS キーの削除には待機期間があります。直後に期待される状態は PendingDeletion であり、キーがすでに消えた証拠ではありません。この期間中、キーは復号できません。
削除をスケジュールする前に、ARN が引き続き自分のエクスポートキーに属していることを確認します。
aws kms describe-key --key-id "$KEY_ARN" --query 'KeyMetadata.[Description,KeyState]' --output text
labex-sec01-owned-export と Enabled が返るはずです。追加したロールへの権限付与と、作成したエイリアスだけを削除します。
aws iam delete-role-policy --role-name labex-sec01-export-reader --policy-name ReadPrivateExport
aws kms delete-alias --alias-name alias/labex-sec01-private-export
最短の 7 日間の待機期間で、キーの削除をスケジュールします。
aws kms schedule-key-deletion --key-id "$KEY_ARN" --pending-window-in-days 7 --query DeletionDate --output text
コマンドは予定された削除日を返します。別の読み取りで実際のキー状態を確認し、無関係な参照キーを保持します。
aws kms describe-key --key-id "$KEY_ARN" --query KeyMetadata.KeyState --output text
aws kms describe-key --key-id alias/labex-sec01-reference --query KeyMetadata.KeyState --output text
自分のキーは PendingDeletion、参照キーは Enabled となるはずです。AWS View には読み取り担当への権限付与がなく、Reference preserved が表示されるはずです。rm -f で、名前を指定したローカルのエクスポート関連ファイルだけを削除します。このコマンドはファイルが存在しなくても処理を続け、他のプロジェクトファイルを削除しません。
rm -f private-export.json private-export.kms restored-export.json read-export.json
操作担当者のプロファイルがまだ使えるうちに、このステップの検証を実行してください。合格後、この VM の使い捨て CLI プロファイルを削除し、キー変数を解除します。これはローカルのセッション認証情報を削除しますが、スケジュールされたクラウドキーの削除を取り消すものではありません。
rm -f /home/labex/.aws/credentials /home/labex/.aws/config
unset KEY_ARN
まとめ
カスタマー管理の KMS キーと秘密ではないコンテキストで実際のエクスポートのバイト列を暗号化し、1 つの読み取りロールに正確なキーへの Decrypt を許可して、元のバイト列を復元しました。誤ったコンテキスト、権限付与の削除、キーの無効化は、それぞれ異なる失敗を引き起こしました。その後、無関係な参照キーを保持しながら、削除待機期間を通じて所有キーを廃止しました。



