[アップデート] Amazon DynamoDBがリソースベースポリシーをサポートしました

クロスアカウントアクセスやリソース側で権限をさらに絞りたい場合に
2024.03.23

別アカウントからのアクセス許可を簡単に行いたい

こんにちは、のんピ(@non____97)です。

皆さんはDynamoDBに対して別アカウントからのアクセス許可を簡単に行いたいなと思ったことはありますか? 私はあります。

従来、別アカウントから自アカウントのDynamoDBにアクセス許可をするためには、自アカウント内のIAMロールにAssume Roleさせてから操作をする必要がありました。手元でAWS CLIで操作する場合はプロファイルを指定するだけなので訳ないですが、Step FunctionsのステートマシンやLambda関数で別アカウントのDynamoDBを操作する際は、都度Assume Roleする必要があり非常に手間です。

Step Functionsでタスク毎にAssume Roleする方法は以下記事をご覧ください。

今回、アップデートによりAmazon DynamoDBでリソースベースポリシーが使えるようになりました。

AWS Blogsにも投稿されていますね。

これにより、他アカウントのユーザーにAssume Roleを依頼することなく、直接操作を依頼することが可能になりました。イメージは先述のAWS Blogの図が分かりやすいです。

リソースベースポリシーがない場合

DBBLOG-3860-img1

リソースベースポリシーがある場合

DBBLOG-3860-img2

また、リソースベースポリシーを使うことで、データストア側で操作できる権限を絞ることができるのもありがたいポイントですね。IAMポリシーで適当に全DynamoDBに許可するようなIAMポリシーをアタッチされても、特定のテーブルには特定のユーザーしかアクセスさせたくないケースもあります。

実際に試してみました。

いきなりまとめ

  • DynamoDBのリソースベースポリシーは以下に対してアクセス許可を設定可能
    • テーブル
    • インデックス
    • ストリーム
  • API毎にリソースベースポリシーで設定可否がある
  • リソースベースポリシーはIAM Access Analyzerとも連携可能
    • 意図しないアクセス許可に気づきやすい
  • リソースベースポリシーを設定する際は検証用のDynamoDBテーブルで評価しよう
    • 設定に誤りがあると、rootユーザーでしか操作できなくなる可能性がある
    • DeleteResourcePolicyの許可があるのであれば、リソースベースポリシーを剥がしてアクセスすることが可能
  • 主な注意事項
    • リソースベースポリシードキュメントの最大サイズは20KB
    • 対象リソースに対するポリシーの更新に成功した場合、対象リソースへのポリシーの更新は15秒間行えない
    • 古いDynamoDBグローバルテーブルのレプリカでは設定できない
    • リソースベースポリシーによってDynamoDBのサービスリンクロールがグローバルテーブルのデータをレプリケートするアクションが拒否された場合、レプリカの追加または削除はエラーで失敗する
    • AWSマネージドキーのキーポリシーは変更できないため、AWSマネージドキーを使用している場合はクロスアカウントアクセスを許可してもアクセスできない

DynamoDBのリソースベースポリシーとは

概要

DynamoDB自身にアタッチするポリシーです。テーブルポリシーとも言うようです。

DynamoDBのリソースベースポリシーの詳細は以下AWS公式ドキュメントにまとまっています。

「そもそもリソースベースポリシーとは?」という方は以下記事をご覧ください。

DynamoDBのリソースベースポリシーはテーブルだけでなく、インデックス、ストリームにも設定することが可能です。具体的にリソースベースポリシーで設定可能なAPIは以下のとおりです。ExportTableToPointInTimeなどクロスアカウントでサポートされていないAPIもあるので注意しましょう。

Data Plane - Tables/indexes

API action Resource-based policy support Cross-account support
DeleteItem Yes Yes
GetItem Yes Yes
PutItem Yes Yes
Query Yes Yes
Scan Yes Yes
UpdateItem Yes Yes
TransactGetItems Yes Yes
TransactWriteItems Yes Yes
BatchGetItem Yes Yes
BatchWriteItem Yes Yes

PartiQL

API action Resource-based policy support Cross-account support
BatchExecuteStatement Yes No
ExecuteStatement Yes No
ExecuteTransaction Yes No

Control Plane - Tables

API action Resource-based policy support Cross-account support
CreateTable No No
DeleteTable Yes Yes
DescribeTable Yes Yes
UpdateTable Yes Yes

Version 2019.11.21 (Current) global tables

API action Resource-based policy support Cross-account support
DescribeTableReplicaAutoScaling Yes No
UpdateTableReplicaAutoScaling Yes No

Version 2017.11.29 (Legacy) global table

API action Resource-based policy support Cross-account support
CreateGlobalTable No No
DescribeGlobalTable No No
DescribeGlobalTableSettings No No
ListGlobalTables No No
UpdateGlobalTable No No
UpdateGlobalTableSettings No No

Tags

API action Resource-based policy support Cross-account support
ListTagsOfResource Yes Yes
TagResource Yes Yes
UntagResource Yes Yes

Backup/Restore

API action Resource-based policy support Cross-account support
CreateBackup Yes No
DescribeBackup No No
DeleteBackup No No
RestoreTableFromBackup No No

Continuous Backup/Restore (PITR)

API action Resource-based policy support Cross-account support
DescribeContinuousBackups Yes No
RestoreTableToPointInTime Yes No
UpdateContinuousBackups Yes No

Contributor Insights

API action Resource-based policy support Cross-account support
DescribeContributorInsights Yes No
ListContributorInsights No No
UpdateContributorInsights Yes No

Export

API action Resource-based policy support Cross-account support
DescribeExport No No
ExportTableToPointInTime Yes No
ListExports No No

Import

API action Resource-based policy support Cross-account support
DescribeImport No No
ImportTable No No
ListImports No No

Kinesis

API action Resource-based policy support Cross-account support
DescribeKinesisStreamingDestination Yes No
DisableKinesisStreamingDestination Yes No
EnableKinesisStreamingDestination Yes No
UpdateKinesisStreamingDestination Yes No

Resource policies

API action Resource-based policy support Cross-account support
GetResourcePolicy Yes No
PutResourcePolicy Yes No
DeleteResourcePolicy Yes No

Time-to-Live

API action Resource-based policy support Cross-account support
DescribeTimeToLive Yes No
UpdateTimeToLive Yes No

DynamoDB Streams

API action Resource-based policy support Cross-account support
DescribeStream Yes Yes
GetRecords Yes Yes
GetShardIterator Yes Yes
ListStreams No No

Others

API action Resource-based policy support Cross-account support
DescribeLimits No No
DescribeEndpoints No No
ListBackups No No
ListTables No No

抜粋 : IAM actions supported by resource-based policies - Amazon DynamoDB

リソースベースポリシーはIAM Access Analyzerとも連携可能です。これにより、別アカウントへの意図しないアクセス許可に気づきやすくなります。IAM Access Analyzerの説明は以下記事をご覧ください。

DynamoDBのリソースベースポリシーでできること

DynamoDBのリソースベースポリシーでできることの一例は以下のとおりです。

  • テーブルに対して特定のユーザーにのみ権限を付与する
    • 特定ユーザー以外は拒否することも可能
  • テーブルの特定のパーティションキーや属性のみに対するクエリ操作のみ許可する
  • 指定した送信元IPアドレスやVPCエンドポイント経由以外からはアクセス拒否する

具体的なポリシーは以下AWS公式ドキュメントに記載があります。

DynamoDB固有の条件キーを使うことで細やかなアクセス制御を行うことが可能です。条件キーの詳細は以下AWS公式ドキュメントをご覧ください。

ちなみに、「拒否する」という設定を入れる場合は非常に注意が必要です。設定に誤りがあると、rootユーザーでしか操作できなくなる可能性があります。検証用のDynamoDBテーブルで評価した上で設定しましょう。CloudFormationで設定する場合は以下記事で紹介しているとおり、Condition句で明示的にCloudFormation経由での実行を許可してあげると良いでしょう。こうすることで何かあった場合でもCloudFormation経由で操作することが可能です。

注意事項

主な注意事項は以下のとおりです。

  • リソースベースポリシードキュメントの最大サイズは20KB
  • 対象リソースに対するポリシーの更新に成功した場合、対象リソースへのポリシーの更新は15秒間行えない
  • 古いDynamoDBグローバルテーブルのレプリカでは設定できない
  • リソースベースポリシーによってDynamoDBのサービスリンクロールがグローバルテーブルのデータをレプリケートするアクションが拒否された場合、レプリカの追加または削除はエラーで失敗する
  • AWSマネージドキーのキーポリシーは変更できないため、AWSマネージドキーを使用している場合はクロスアカウントアクセスを許可してもアクセスできない

S3のようにアクセスポイントはないので、Condtion句が複雑だったり、対象のステートメントを記述している場合は20KBに到達はしやすいかと思います。

詳細は以下AWS公式ドキュメントをご覧ください。

やってみた

クロスアカウントアクセスの許可

実際に試してみます。

まずはクロスアカウントアクセスを許可を試します。

デフォルトではDynamoDBテーブルはリソースベースポリシーは設定されていません。

テーブルを表示___Amazon_DynamoDB_Management_Console___DynamoDB___us-east-1

この状態で別アカウントからDynamoDBテーブルの情報を参照してみます。

$ aws dynamodb describe-table \
    --table-name arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer

An error occurred (AccessDeniedException) when calling the DescribeTable operation: User: arn:aws:sts::<別AWSアカウントID>:assumed-role/<IAMロール名>/<セッション名> is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer because no resource-based policy allows the dynamodb:DescribeTable action

はい、拒否されました。

それでは、別アカウントのIAMロールのセッションのアクセスを許可します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:sts::<別AWSアカウントID>:assumed-role/<IAMロール名>/<セッション名>"
      },
      "Action": "dynamodb:DescribeTable",
      "Resource": "arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer"
    }
  ]
}

許可したいアクションの一覧やプリンシパル、条件などもマネジメントコンソールからポチポチできます。

テーブルについてのリソースベースのポリシーを作成___Amazon_DynamoDB_Management_Console___DynamoDB___us-east-1

外部アクセスをプレビューをクリックすると、IAM Access Analyzerを使って、どんな許可が行われるのか分析してくれます。

外部アクセスをプレビュー

リソースベースポリシーを更新すると、以下のようになります。IAM Access Analyzerの検出内容も表示してくれるので親切です。

テーブル analyzer についてのリソースベースのポリシーが正常に更新されました。

アクセス許可後、再度別アカウントから同じ操作をしてみます。

$ aws dynamodb describe-table \
    --table-name arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "ArchiveRuleName",
                "AttributeType": "S"
            }
        ],
        "TableName": "analyzer",
        "KeySchema": [
            {
                "AttributeName": "ArchiveRuleName",
                "KeyType": "HASH"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2023-03-14T03:02:01.840000+00:00",
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 0,
            "WriteCapacityUnits": 0
        },
        "TableSizeBytes": 1211,
        "ItemCount": 4,
        "TableArn": "arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer",
        "TableId": "cd86261d-5b37-46ee-abc3-ec6cd62fae3f",
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST",
            "LastUpdateToPayPerRequestDateTime": "2023-03-14T03:02:01.840000+00:00"
        },
        "TableClassSummary": {
            "TableClass": "STANDARD"
        },
        "DeletionProtectionEnabled": false
    }
}

拒否されずに取得できました。これは簡単です。

ちなみにリソースベースポリシーを短時間で更新するとResource-based policy for table analyzer modified within the previous 15000 milliseconds. Please try again after 2024-03-23T06-59-15.747Zと怒られました。15秒間隔を空けましょう。

Resource-based policy for table analyzer modified within the previous 15000 milliseconds. Please try again after 2024-03-23T06-59-15.747Z

特定のIAMロールからのアクセス以外は拒否

続いて、特定のIAMロールからのアクセス以外は拒否するようにしてみます。

特定のIAMロールからのアクセス以外は拒否する場合、以下記事で紹介しているとおりaws:userIdを使います。

実際には以下のように行います。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "dynamodb:*",
      "Resource": "arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer",
      "Condition": {
        "StringNotLike": {
          "aws:userId": "AROXXXXXXXXXXXX:*"
        }
      }
    }
  ]
}

こちらのポリシーを設定後、許可しているIAMロール以外からアクセスをすると以下のようにアクセスできませんでした。

テーブルの詳細をロードできません

もちろん、許可しているIAMロールを使用している場合はアクセスできました。ただし、IAM Access Analyzerで使用しているIAMロールは許可されていないのでアクセスレベルがエラーとなっていますね。

許可しているIAMロールでは操作可能

もし、設定を間違えて誰もアクセスできなくなった場合はrootユーザーでリソースベースポリシーを変更しましょう。

また、DeleteResourcePolicyの許可があるのであれば、以下のようにリソースベースポリシーを剥がしてあげることで対処することが可能です。

$ aws dynamodb delete-resource-policy \
    --resource-arn arn:aws:dynamodb:us-east-1:<AWSアカウントID>:table/analyzer
{
    "RevisionId": "1711178503038"
}

クロスアカウントアクセスやリソース側で権限をさらに絞りたい場合に

Amazon DynamoDBでリソースベースポリシーが使えるようになったアップデートを紹介しました。

クロスアカウントアクセスやリソース側で権限をさらに絞りたい場合に非常に有用ですね。十分に検証した上で積極的に使っていきたいです。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!