

# DynamoDB 테이블 및 인덱스와 함께 ABAC를 사용하는 예제
<a name="abac-example-use-cases"></a>

다음 예제에서는 태그를 사용하여 속성 기반 조건을 구현하는 몇 가지 사용 사례를 보여줍니다.

**Topics**
+ [예제 1: aws:ResourceTag를 사용하여 작업 허용](#abac-allow-example-resource-tag)
+ [예제 2: aws:RequestTag를 사용하여 작업 허용](#abac-allow-example-request-tag)
+ [예제 3: aws:TagKeys를 사용하여 작업 거부](#abac-deny-example-tag-key)

## 예제 1: aws:ResourceTag를 사용하여 작업 허용
<a name="abac-allow-example-resource-tag"></a>

`aws:ResourceTag/tag-key` 조건 키를 사용하여 IAM 정책에 지정된 태그 키-값 페어를 DynamoDB 테이블에 연결된 키-값 페어와 비교할 수 있습니다. 예를 들어 IAM 정책 및 테이블의 태그 조건이 일치하는 경우 [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)과 같은 특정 작업을 허용할 수 있습니다. 이렇게 하려면 다음 단계를 수행하세요.

------
#### [ Using the AWS CLI ]

1. 테이블 만들기. 다음 예제에서는 [create-table](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html) AWS CLI 명령을 사용하여 `myMusicTable`이라는 테이블을 생성합니다.

   ```
   aws dynamodb create-table \
     --table-name myMusicTable \
     --attribute-definitions AttributeName=id,AttributeType=S \
     --key-schema AttributeName=id,KeyType=HASH \
     --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
     --region us-east-1
   ```

1. 이 테이블에 태그를 추가합니다. 다음 [tag-resource](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/tag-resource.html) AWS CLI 명령 예제는 태그 키-값 페어 `Title: ProductManager`를 `myMusicTable`에 추가합니다.

   ```
   aws dynamodb tag-resource --region us-east-1 --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable --tags Key=Title,Value=ProductManager
   ```

1. 다음 예제와 같이 [인라인 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)을 만들고 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 관리형 정책이 연결된 역할에 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "dynamodb:PutItem",
         "Resource": "arn:aws:dynamodb:*:*:table/*",
         "Condition": {
           "StringEquals": {
             "aws:ResourceTag/Title": "ProductManager"
           }
         }
       }
     ]
   }
   ```

------

   이 정책은 테이블에 연결된 태그 키와 값이 정책에 지정된 태그와 일치할 때 테이블에 대한 `PutItem` 작업을 허용합니다.

1. 3단계에 설명된 정책으로 역할을 수임합니다.

1. [put-item](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/put-item.html) AWS CLI 명령을 사용하여 항목을 `myMusicTable`에 입력합니다.

   ```
   aws dynamodb put-item \
       --table-name myMusicTable --region us-east-1 \
       --item '{
           "id": {"S": "2023"},
           "title": {"S": "Happy Day"},
           "info": {"M": {
               "rating": {"N": "9"},
               "Artists": {"L": [{"S": "Acme Band"}, {"S": "No One You Know"}]},
               "release_date": {"S": "2023-07-21"}
           }}
       }'
   ```

1. 테이블을 스캔하여 항목이 테이블에 추가되었는지 확인합니다.

   ```
   aws dynamodb scan --table-name myMusicTable  --region us-east-1
   ```

------
#### [ Using the AWS SDK for Java 2.x ]

1. 테이블 만들기. 다음 예제에서는 [CreateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html) API를 사용하여 `myMusicTable`이라는 테이블을 생성합니다.

   ```
   DynamoDbClient dynamoDB = DynamoDbClient.builder().region(region).build();
   CreateTableRequest createTableRequest = CreateTableRequest.builder()
       .attributeDefinitions(
           Arrays.asList(
               AttributeDefinition.builder()
               .attributeName("id")
               .attributeType(ScalarAttributeType.S)
               .build()
           )
       )
       .keySchema(
           Arrays.asList(
               KeySchemaElement.builder()
               .attributeName("id")
               .keyType(KeyType.HASH)
               .build()
           )
       )
       .provisionedThroughput(ProvisionedThroughput.builder()
           .readCapacityUnits(5L)
           .writeCapacityUnits(5L)
           .build()
       )
       .tableName("myMusicTable")
       .build();
   
   CreateTableResponse createTableResponse = dynamoDB.createTable(createTableRequest);
   String tableArn = createTableResponse.tableDescription().tableArn();
   String tableName = createTableResponse.tableDescription().tableName();
   ```

1. 이 테이블에 태그를 추가합니다. 다음 예제의 [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html) API는 태그 키-값 페어 `Title: ProductManager`를 `myMusicTable`에 추가합니다.

   ```
   TagResourceRequest tagResourceRequest = TagResourceRequest.builder()
       .resourceArn(tableArn)
       .tags(
           Arrays.asList(
               Tag.builder()
               .key("Title")
               .value("ProductManager")
               .build()
           )
       )
       .build();
   dynamoDB.tagResource(tagResourceRequest);
   ```

1. 다음 예제와 같이 [인라인 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)을 만들고 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 관리형 정책이 연결된 역할에 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "dynamodb:PutItem",
         "Resource": "arn:aws:dynamodb:*:*:table/*",
         "Condition": {
           "StringEquals": {
             "aws:ResourceTag/Title": "ProductManager"
           }
         }
       }
     ]
   }
   ```

------

   이 정책은 테이블에 연결된 태그 키와 값이 정책에 지정된 태그와 일치할 때 테이블에 대한 `PutItem` 작업을 허용합니다.

1. 3단계에 설명된 정책으로 역할을 수임합니다.

1. [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) API를 사용하여 항목을 `myMusicTable`에 입력합니다.

   ```
   HashMap<String, AttributeValue> info = new HashMap<>();
   info.put("rating", AttributeValue.builder().s("9").build());
   info.put("artists", AttributeValue.builder().ss(List.of("Acme Band","No One You Know").build());
   info.put("release_date", AttributeValue.builder().s("2023-07-21").build());
   
   HashMap<String, AttributeValue> itemValues = new HashMap<>();
   itemValues.put("id", AttributeValue.builder().s("2023").build());
   itemValues.put("title", AttributeValue.builder().s("Happy Day").build());
   itemValues.put("info", AttributeValue.builder().m(info).build());
   
   
   PutItemRequest putItemRequest = PutItemRequest.builder()
                   .tableName(tableName)
                   .item(itemValues)
                   .build();
   dynamoDB.putItem(putItemRequest);
   ```

1. 테이블을 스캔하여 항목이 테이블에 추가되었는지 확인합니다.

   ```
   ScanRequest scanRequest = ScanRequest.builder()
                   .tableName(tableName)
                   .build();
                   
   ScanResponse scanResponse = dynamoDB.scan(scanRequest);
   ```

------
#### [ Using the AWS SDK for Python (Boto3) ]

1. 테이블 만들기. 다음 예제에서는 [CreateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html) API를 사용하여 `myMusicTable`이라는 테이블을 생성합니다.

   ```
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 5,
           'WriteCapacityUnits': 5
       },
   )
   
   table_arn = create_table_response['TableDescription']['TableArn']
   ```

1. 이 테이블에 태그를 추가합니다. 다음 예제의 [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html) API는 태그 키-값 페어 `Title: ProductManager`를 `myMusicTable`에 추가합니다.

   ```
   tag_resouce_response = ddb_client.tag_resource(
       ResourceArn=table_arn,
       Tags=[
           {
               'Key': 'Title',
               'Value': 'ProductManager'
           },
       ]
   )
   ```

1. 다음 예제와 같이 [인라인 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)을 만들고 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 관리형 정책이 연결된 역할에 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
           "Effect": "Allow",
           "Action": "dynamodb:PutItem",
           "Resource": "arn:aws:dynamodb:*:*:table/*",
           "Condition": {
               "StringEquals": {
               "aws:ResourceTag/Title": "ProductManager"
               }
           }
           }
       ]
       }
   ```

------

   이 정책은 테이블에 연결된 태그 키와 값이 정책에 지정된 태그와 일치할 때 테이블에 대한 `PutItem` 작업을 허용합니다.

1. 3단계에 설명된 정책으로 역할을 수임합니다.

1. [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) API를 사용하여 항목을 `myMusicTable`에 입력합니다.

   ```
   put_item_response = client.put_item(
       TableName = 'myMusicTable'
       Item = {
           'id': '2023',
           'title': 'Happy Day',
           'info': {
               'rating': '9',
               'artists': ['Acme Band','No One You Know'],
               'release_date': '2023-07-21'
           }
       }
   )
   ```

1. 테이블을 스캔하여 항목이 테이블에 추가되었는지 확인합니다.

   ```
   scan_response = client.scan(
       TableName='myMusicTable'
   )
   ```

------

**ABAC이 없는 경우**  
AWS 계정에 ABAC가 활성화되지 않은 경우 IAM 정책 및 DynamoDB 테이블의 태그 조건이 일치하지 않습니다. 따라서 이 `PutItem` 작업은 `AmazonDynamoDBReadOnlyAccess` 정책의 영향으로 인해 `AccessDeniedException`을 반환합니다.

```
An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::123456789012:assumed-role/DynamoDBReadOnlyAccess/Alice is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable because no identity-based policy allows the dynamodb:PutItem action.
```

**ABAC가 있는 경우**  
AWS 계정에 ABAC가 활성화된 경우 `put-item` 작업이 성공적으로 완료되고 테이블에 새 항목이 추가됩니다. 이는 테이블의 인라인 정책이 IAM 정책과 테이블의 태그 조건이 일치하는 경우 `PutItem` 작업을 허용하기 때문입니다.

## 예제 2: aws:RequestTag를 사용하여 작업 허용
<a name="abac-allow-example-request-tag"></a>

[aws:RequestTag/tag-key](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requesttag) 조건 키를 사용하여 요청에 전달된 태그 키-값 페어를 IAM 정책에 지정된 태그 페어와 비교할 수 있습니다. 예를 들어 태그 조건이 일치하지 않는 경우 `aws:RequestTag`를 사용하여와 `CreateTable`과 같은 특정 작업을 허용할 수 있습니다. 이렇게 하려면 다음 단계를 수행하세요.

------
#### [ Using the AWS CLI ]

1. 다음 예제와 같이 [인라인 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)을 만들고 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html) AWS 관리형 정책이 연결된 역할에 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "StringEquals": {
                       "aws:RequestTag/Owner": "John"
                   }
               }
           }
       ]
   }
   ```

------

1. `"Owner": "John"`의 태그 키-값 페어가 포함된 테이블을 만듭니다.

   ```
   aws dynamodb create-table \
   --attribute-definitions AttributeName=ID,AttributeType=S \
   --key-schema AttributeName=ID,KeyType=HASH  \
   --provisioned-throughput ReadCapacityUnits=1000,WriteCapacityUnits=500 \
   --region us-east-1 \
   --tags Key=Owner,Value=John \
   --table-name myMusicTable
   ```

------
#### [ Using the AWS SDK for Python (Boto3) ]

1. 다음 예제와 같이 [인라인 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)을 만들고 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 관리형 정책이 연결된 역할에 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "StringEquals": {
                       "aws:RequestTag/Owner": "John"
                   }
               }
           }
       ]
   }
   ```

------

1. `"Owner": "John"`의 태그 키-값 페어가 포함된 테이블을 만듭니다.

   ```
   ddb_client = boto3.client('dynamodb')
   
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 1000,
           'WriteCapacityUnits': 500
       },
       Tags=[
           {
               'Key': 'Owner',
               'Value': 'John'
           },
       ],
   )
   ```

------

**ABAC이 없는 경우**  
AWS 계정에 ABAC가 활성화되지 않은 경우 인라인 정책 및 DynamoDB 테이블의 태그 조건이 일치하지 않습니다. 따라서 `CreateTable` 요청이 실패하고 테이블이 생성되지 않습니다.

```
An error occurred (AccessDeniedException) when calling the CreateTable operation: User: arn:aws:sts::123456789012:assumed-role/Admin/John is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable because no identity-based policy allows the dynamodb:CreateTable action.
```

**ABAC가 있는 경우**  
AWS 계정에 ABAC가 활성화된 경우 테이블 만들기 요청이 성공적으로 완료됩니다. 태그 키-값 쌍 `"Owner": "John"`이 `CreateTable` 요청에 있으므로 인라인 정책을 통해 사용자 `John`이 `CreateTable` 작업을 수행할 수 있습니다.

## 예제 3: aws:TagKeys를 사용하여 작업 거부
<a name="abac-deny-example-tag-key"></a>

[aws:TagKeys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-tagkeys) 조건 키를 사용하여 요청의 태그 키를 IAM 정책에 지정된 키와 비교할 수 있습니다. 예를 들어 요청에 특정 태그 키가 *없는* 경우 `aws:TagKeys`를 사용하여 `CreateTable`과 같은 특정 작업을 거부할 수 있습니다. 이렇게 하려면 다음 단계를 수행하세요.

------
#### [ Using the AWS CLI ]

1. 다음 예제와 같이 [AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) AWS 관리형 정책이 연결된 역할에 [고객 관리형 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)을 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Deny",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "Null": {
                       "aws:TagKeys": "false"
                   },
                   "ForAllValues:StringNotEquals": {
                       "aws:TagKeys": "CostCenter"
                   }
               }
           }
       ]
   }
   ```

------

1. 정책이 연결된 역할을 수임하고 태그 키 `Title`로 테이블을 만듭니다.

   ```
   aws dynamodb create-table \
   --attribute-definitions AttributeName=ID,AttributeType=S \
   --key-schema AttributeName=ID,KeyType=HASH  \
   --provisioned-throughput ReadCapacityUnits=1000,WriteCapacityUnits=500 \
   --region us-east-1 \
   --tags Key=Title,Value=ProductManager \
   --table-name myMusicTable
   ```

------
#### [ Using the AWS SDK for Python (Boto3) ]

1. 다음 예제와 같이 [AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) AWS 관리형 정책이 연결된 역할에 [고객 관리형 정책](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)을 추가합니다.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Deny",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "Null": {
                       "aws:TagKeys": "false"
                   },
                   "ForAllValues:StringNotEquals": {
                       "aws:TagKeys": "CostCenter"
                   }
               }
           }
       ]
   }
   ```

------

1. 정책이 연결된 역할을 수임하고 태그 키 `Title`로 테이블을 만듭니다.

   ```
   ddb_client = boto3.client('dynamodb')
   
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 1000,
           'WriteCapacityUnits': 500
       },
       Tags=[
           {
               'Key': 'Title',
               'Value': 'ProductManager'
           },
       ],
   )
   ```

------

**ABAC이 없는 경우**  
AWS 계정에 ABAC가 활성화되지 않은 경우 DynamoDB는 `create-table` 명령의 태그 키를 IAM으로 전송하지 않습니다. `Null` 조건은 요청에 태그 키가 없는 경우 조건이 `false`로 평가되도록 합니다. `Deny` 정책이 일치하지 않으므로 `create-table` 명령이 성공적으로 완료됩니다.

**ABAC가 있는 경우**  
AWS 계정에 ABAC가 활성화된 경우 `create-table` 명령에 전달된 태그 키가 IAM으로 전달됩니다. 태그 키 `Title`은 `Deny` 정책에 있는 조건 기반 태그 키 `CostCenter`를 기준으로 평가됩니다. `StringNotEquals` 연산자로 인해 태그 키 `Title`이 `Deny` 정책에 있는 태그 키와 일치하지 않습니다. 따라서 `CreateTable` 작업이 실패하고 테이블이 생성되지 않습니다. `create-table` 명령을 실행하면 `AccessDeniedException`이 반환됩니다.

```
An error occurred (AccessDeniedException) when calling the CreateTable operation: User: arn:aws:sts::123456789012:assumed-role/DynamoFullAccessRole/ProductManager is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable with an explicit deny in an identity-based policy.
```