KMS で非公開エクスポートを暗号化・復号する

AWSBeginner
オンラインで実践に進む

はじめに

非公開エクスポートは保存前に暗号化する必要があります。小さな合成ファイルを暗号化し、1 つの読み取り担当に元のバイト列を復元させ、復号の失敗を診断して、キーの削除をスケジュールします。

先に レポートの読み取り役に最小権限を与える と 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 の暗号化、復号権限、キーの状態。

ラボの概要

概念図:KMS で合成の非公開エクスポートをローカルの暗号文に変換し、読み取りロールのセッションが権限、一致するコンテキスト、有効なキーを使って元のバイトを復元します。出典:公式 draw.io AWS4 図形。

非公開エクスポートを暗号化する

このステップでは、AWS Key Management Service(KMS) のキーを作成し、提供されたエクスポートを暗号文に変換します。個人データの代わりに、提供された合成データ private-export.json を使ってください。export-reader プロファイルは、準備済みの読み取りロールの一時セッションを使います。最初は KMS 権限がありません。alias/labex-sec01-reference を保持してください。

IAM では、誰が操作を要求できるかを学びました。ここでは、その操作でエクスポートの元のバイト列を復元します。暗号化ファイルを受け渡すには、対象の読み取りロールに復号権限があり、コンテキストが一致し、キーが使用可能である必要があります。

上部の 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)
echo "$KEY_ARN"
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 が返るはずです。参照キーを使用したり変更したりしないでください。

AWS KMS 公式コンソールのキー設定 — 出典:AWS KMS https://docs.aws.amazon.com/kms/latest/developerguide/find-cmk-id-arn.html

公式コンソールの参考画像:エイリアス、Enabled 状態、ARN は、先ほどクエリしたキーの識別情報と状態に対応します。画像は AWS の例の値です。Terminal では引き続き自分の KEY_ARN を使ってください。

暗号化コンテキストは、暗号文に結び付けられた秘密ではないラベルの集合です。復号では同じラベルを指定する必要があります。ここでは 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 はバイト列の復元を許可しますが、暗号化やキーの管理は許可しません。

KMS 復号の境界 — 読み取り担当がエクスポートを復元するには、正しいコンテキスト、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 に限定してください。

正確なキーへの読み取り権限付与と実際のバイト列復元を示す AWS View の例

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 テーブルを確認します。拒否されたリクエストの呼び出し元、コンテキスト、結果を比較してください。ロールへの権限付与では、コンテキストの不一致や無効なキーを修復できません。

拒否されたリクエストと、その後復元された読み取りアクセスを示す AWS View の例

所有するキーを安全に廃止する

このステップでは、読み取り担当への権限付与とエイリアスを削除し、自分のエクスポートキーだけの削除をスケジュールします。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 を許可して、元のバイト列を復元しました。誤ったコンテキスト、権限付与の削除、キーの無効化は、それぞれ異なる失敗を引き起こしました。その後、無関係な参照キーを保持しながら、削除待機期間を通じて所有キーを廃止しました。

詳しくは、AWS 公式ドキュメントを参照してください:暗号化コンテキストと暗号文の結び付け; KMS キーの削除と待機期間。