概要
AWS KMSのカスタマー管理キーは、キーポリシーを使ってアクセスを細かく制御できます。KMS鍵タイプ(AWS所有/AWS管理/カスタマー管理)の違いについては過去の記事で解説していますが、本記事ではキーポリシーの 条件キー(Condition Key) に焦点を当てます。
特に kms:ViaService 条件キーは、KMSキーの使用を特定のAWSサービスからのリクエストに限定できる仕組みです。たとえば「このKMSキーはus-west-1リージョンのS3からのリクエストでのみ使用を許可する」といった制御が可能になります。
本記事では、kms:ViaService 条件キーを使ったキーポリシーを設定し、S3経由でのKMS操作は成功するが、直接のKMS API呼び出しでは失敗することを確認します。

この記事のメリット
- KMSキーポリシーにおける条件キーの役割と記述方法を理解できる
kms:ViaService条件キーの仕組みと記述形式を正確に把握できるPrincipalに"AWS": "*"を指定した場合のkms:CallerAccount条件キーによるアカウント制限の方法を学べる- S3のSSE-KMS暗号化設定と、KMSキーポリシーとの連携を実践できる
- SCS試験で「KMSキーポリシーの条件キー」に関する問いに正確に答えられるようになる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

クラウドおさる
クラウドおさるはじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
KMSキーポリシーの基本構造
KMSキーポリシーは、KMSキーへのアクセスを制御するリソースベースのポリシーです。IAMポリシーと同様に、Effect、Principal、Action、Resource、Condition で構成されます。
{
"Sid": "ステートメントの識別子",
"Effect": "Allow",
"Principal": { "AWS": "..." },
"Action": [ "kms:Decrypt", "kms:GenerateDataKey" ],
"Resource": "*",
"Condition": {
"StringEquals": {
"条件キー": "条件値"
}
}
}キーポリシーの Resource は常に "*" です。キーポリシーはそのKMSキー自体に適用されるため、Resource にキーのARNを指定する必要はありません。
kms:ViaService 条件キーとは
kms:ViaService は、KMSキーの使用を 特定のAWSサービス経由のリクエストに限定する 条件キーです。AWSサービスがユーザーの代わりにKMS APIを呼び出す場合(たとえばS3がオブジェクトを暗号化する際にKMSを呼び出す場合)、KMSはリクエストの送信元サービスを識別できます。
kms:ViaService の値は以下の形式で指定します。
<サービス名>.<リージョン>.amazonaws.com例:
- S3(us-west-1):
s3.us-west-1.amazonaws.com - EBS(ap-northeast-1):
ec2.ap-northeast-1.amazonaws.com - RDS(ap-northeast-1):
rds.ap-northeast-1.amazonaws.com
この条件キーを使うことで、以下のような制御が可能です。
| 制御の例 | kms:ViaService の値 |
|---|---|
| 東京リージョンのS3からのみ許可 | s3.ap-northeast-1.amazonaws.com |
| us-west-1のS3からのみ許可 | s3.us-west-1.amazonaws.com |
| 東京リージョンのEBSからのみ許可 | ec2.ap-northeast-1.amazonaws.com |
Principal “*” と kms:CallerAccount の組み合わせ
キーポリシーの Principal に "AWS": "*" を指定すると、すべてのAWSプリンシパルが対象になります。しかし、これだけでは他のAWSアカウントからのアクセスも許可されてしまいます。
そこで kms:CallerAccount 条件キーを組み合わせて、特定のアカウントに制限します。
"Principal": { "AWS": "*" },
"Condition": {
"StringEquals": {
"kms:CallerAccount": "111122223333"
}
}kms:CallerAccount は、リクエストを送ったプリンシパルが属するAWSアカウントIDと比較される条件キーです。この条件により、そのアカウント内のすべてのIAMエンティティ(ユーザー、ロール)からのリクエストが許可されます。
aws:PrincipalArnでは代用できません。aws:PrincipalArnはリクエスト元プリンシパルのARNそのもの(例:arn:aws:iam::111122223333:user/alice)と比較されるため、arn:aws:iam::111122223333:rootを指定してもアカウント内のIAMユーザーには一致せず、リクエストは拒否されます。アカウント単位で判定したい場合はkms:CallerAccount(またはグローバル条件キーのaws:PrincipalAccount)を使います。
"Principal": { "AWS": "arn:aws:iam::111122223333:root" }と直接指定する方法もありますが、Principalに"*"を置きConditionで制限するパターンは、より柔軟な条件設定が可能です。
kms:ViaService と kms:CallerAccount の組み合わせ
この2つの条件キーを組み合わせることで、「特定アカウントの、特定リージョンの特定サービスからのリクエストのみ許可する」という厳密な制御が実現できます。
{
"Sid": "Allow access through S3 for all principals in the account",
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "111122223333",
"kms:ViaService": "s3.us-west-1.amazonaws.com"
}
}
}このポリシーステートメントのポイントを整理します。
| 要素 | 設定値 | 意味 |
|---|---|---|
Principal | "AWS": "*" | すべてのAWSプリンシパルが対象 |
Action | kms:Decrypt, kms:GenerateDataKey | 復号とデータキー生成のみ許可(暗号化操作に必要な最小限の権限) |
kms:CallerAccount | 自アカウントID | 特定アカウント内のエンティティに限定 |
kms:ViaService | s3.us-west-1.amazonaws.com | us-west-1リージョンのS3経由のリクエストのみ許可 |
Condition ブロック内の複数の条件キーは AND条件 で評価されます。したがって、kms:CallerAccount と kms:ViaService の両方の条件を満たすリクエストのみが許可されます。
実践
前提条件
- リージョン:
ap-northeast-1(東京) - IAMユーザーまたはロールに
kms:*とs3:*の権限があること - 自身のAWSアカウントIDが確認できていること
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| KMSキー | s3-via-service-key | kms:ViaService条件付きのカスタマー管理キー |
| S3バケット | kms-via-service-test-<アカウントID> | SSE-KMS暗号化の検証用バケット |
ステップ1: カスタマー管理KMSキーを作成する
まず、カスタマー管理のKMSキーを作成します。
- AWSマネジメントコンソールにログインし、リージョンが
ap-northeast-1(東京)であることを確認します - 上部の検索バーに
KMSと入力し、表示された「Key Management Service」を選択します - 左側ナビゲーションの「カスタマー管理型のキー」を選択します
- 「キーの作成」をクリックします。キーの作成は6ステップのウィザードで進みます
- 「ステップ 1: キーを設定」で以下を選択し、「次へ」をクリックします
- キーのタイプ:
対称(デフォルト) - キーの使用法:
暗号化および復号化(デフォルト) - 「ステップ 2: ラベルを追加」で以下を入力します
- エイリアス:
s3-via-service-key - 説明:
kms:ViaService条件キーの検証用


- 「次へ」をクリックします
- 「ステップ 3: キーの管理アクセス許可を定義」で、現在ログインしているIAMユーザーまたはロールにチェックを入れます
- 「次へ」をクリックします
- 「ステップ 4: キーの使用法アクセス許可を定義」では何も選択せずに「次へ」をクリックします(使用許可はキーポリシーで直接制御するため)
ステップ2: kms:ViaService条件付きのキーポリシーを設定する
「ステップ 5: キーポリシーを編集」でポリシーのプレビューが表示されます。「編集」をクリックしてエディタを開き、ポリシー全体を次の内容に置き換えます。
注意:
ACCOUNT_IDはご自身のAWSアカウントID、USER_NAMEはキー管理者にするIAMユーザー名に置き換えてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID:user/USER_NAME" },
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Enable*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "AllowS3ViaServiceOnly",
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "ACCOUNT_ID",
"kms:ViaService": "s3.ap-northeast-1.amazonaws.com"
}
}
}
]
}ここでのポイントは2つあります。
- デフォルトで入っている
Enable IAM User Permissions(アカウントのルートにkms:*を許可するステートメント)を削除する。このステートメントを残すと、IAMポリシーでkms:*を持つユーザーはキーポリシーの条件に関係なくKMS APIを直接呼べてしまい、kms:ViaServiceの効果を確認できません - キー管理者のステートメントに
kms:Create*を含める。エイリアスの作成(kms:CreateAlias)にこの権限が必要で、含めないとキーは作成されてもエイリアスの作成がAccessDeniedExceptionで失敗します
このステートメントにより、以下の条件をすべて満たすリクエストのみが kms:Decrypt と kms:GenerateDataKey の実行を許可されます。
- 自アカウント内のIAMエンティティからのリクエストであること
- ap-northeast-1リージョンのS3サービス経由のリクエストであること


- 「次へ」をクリックし、「ステップ 6: 確認」で内容を確認して「完了」をクリックします
作成されたキーの詳細画面で、エイリアスが s3-via-service-key、ステータスが「有効」であることを確認します。


作成されたキーのARNを控えておきます。後のステップで使用します。
ステップ3: S3バケットを作成しSSE-KMS暗号化を設定する
作成したKMSキーを使って暗号化するS3バケットを作成します。
- 上部の検索バーに
S3と入力し、表示された「S3」を選択します - 「バケットを作成」をクリックします
- AWS リージョンが「アジアパシフィック (東京) ap-northeast-1」であることを確認します
- バケット名に
kms-via-service-test-<アカウントID>と入力します(例:kms-via-service-test-111122223333) - 「デフォルトの暗号化」セクションで以下を設定します
- 暗号化タイプ:
AWS Key Management Service キーを使用したサーバー側の暗号化 (SSE-KMS)を選択 - AWS KMS キー:
AWS KMS キーから選択するを選択し、一覧からs3-via-service-keyのキーARNを選択します - バケットキー:
有効にするのまま


- その他の項目はデフォルトのままにします
- 「バケットを作成」をクリックします
ステップ4: S3経由でのアップロードを確認する(成功)
S3コンソールからファイルをアップロードし、KMSキーが正常に使用されることを確認します。
- 作成したバケット
kms-via-service-test-<アカウントID>を開きます - 「アップロード」をクリックします
- テスト用のファイル(テキストファイルなど)を選択します
- 「アップロード」をクリックします


アップロードが成功します。S3がユーザーの代わりにKMS APIを呼び出してオブジェクトを暗号化しているため、kms:ViaService 条件が満たされ、KMSキーの使用が許可されています。
- アップロードしたオブジェクトをクリックし、詳細画面の「サーバー側の暗号化設定」セクションを確認します
- 暗号化タイプが SSE-KMS で、暗号化キー ARN が
s3-via-service-keyのものであることを確認します


ステップ5: 直接のKMS API呼び出しを確認する(失敗)
次に、AWS CLIを使ってKMS APIを直接呼び出し、kms:ViaService 条件により拒否されることを確認します。
KMSキーのキーIDを使って、直接 kms:GenerateDataKey を呼び出します。
aws kms generate-data-key \
--key-id alias/s3-via-service-key \
--key-spec AES_256 \
--region ap-northeast-1以下のようなエラーメッセージが表示されます。
An error occurred (AccessDeniedException) when calling the GenerateDataKey operation: User: arn:aws:iam::ACCOUNT_ID:user/USER_NAME is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:ap-northeast-1:ACCOUNT_ID:key/KEY_ID because no resource-based policy allows the kms:GenerateDataKey action

このエラーは、KMS APIが直接呼び出されたため kms:ViaService 条件(S3経由であること)が満たされず、リクエストが拒否されたことを示しています。
同じユーザーがS3経由ではKMSキーを使用でき、直接のAPI呼び出しでは使用できないことが確認できました。これが kms:ViaService 条件キーによるサービス別アクセス制御の効果です。
まとめ
本記事のポイントを整理します。
- kms:ViaService は、KMSキーの使用を特定のAWSサービス経由のリクエストに限定する条件キーです。値は
<サービス名>.<リージョン>.amazonaws.comの形式で指定します - Principal
"AWS": "*"とkms:CallerAccountの組み合わせ により、すべてのプリンシパルを対象にしつつ、特定アカウントに制限できます。aws:PrincipalArnにアカウントのルートARNを指定してもIAMユーザーには一致しないため、アカウント単位の判定には使えません - Condition ブロック内の複数の条件キーはAND条件 で評価されます。
kms:CallerAccountとkms:ViaServiceの両方を満たすリクエストのみが許可されます - S3のSSE-KMS暗号化 では、S3がユーザーの代わりにKMS APIを呼び出すため
kms:ViaService条件が満たされますが、ユーザーがKMS APIを直接呼び出す場合は条件が満たされず拒否されます Actionには暗号化操作に必要な最小限の権限(kms:Decryptとkms:GenerateDataKey)のみを指定し、最小権限の原則 を適用します
参照先
- AWS KMS の条件キー – AWS Key Management Service
- kms:ViaService – AWS Key Management Service
- AWS KMS のキーポリシー – AWS Key Management Service
- Amazon S3 でのサーバー側の暗号化によるデータの保護 – Amazon Simple Storage Service
- AWS KMS キーによるサーバー側の暗号化 (SSE-KMS) の使用 – Amazon Simple Storage Service












