セッションタグによるAttribute-based access control (ABAC)を試してみた

セッションタグによるAttribute-based access control (ABAC)を試してみました。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_session-tags.html
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/introduction_attribute-based-access-control.html


## 必要なもの

AWSアカウント

## 手順

1. Roleを作成する
2. IAM Userを作成する
3. Pamameter storeを作成する
4. テスト結果


## 今回試した構成


![sessiontag2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192584/05a0b768-222a-d8af-de4b-3babeb81b21d.png)


1. IAM UserのポリシーでIAM Userのタグ(aws:PrincipalTag)とIAMロールのタグ(aws:ResourceTag)を比較し、同じならロールへのスイッチを許可する
2. IAM RoleのポリシーでIAM Roleのタグ(aws:PrincipalTag)とSSM Parameter storeのタグ(aws:ResourceTag)を比較し、同じならParameter storeへのアクセスを許可する。

## 1. Roleを作成する

### Role

|role|policy|tag|
|---|---|---|
|test-stg-role|test-role-policy|env:stg|
|test-dev-role|test-role-policy|env:dev|

### Role用Policy

```test-role-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "TestAccessSSM",
            "Effect": "Allow",
            "Action": [
                "ssm:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/env": "${aws:PrincipalTag/env}"
                }
            }
        }
    ]
}
```

### Role用Trust relationship

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
```

## 2. IAM Userを作成する

### IAM User

|role|policy|tag|
|---|---|---|
|test-stg|test-user-policy|env:stg|
|test-dev|test-user-policy|env:dev|


### IAM User用Policy



```test-user-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "TestAssumeRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::XXXXXXXXXXXX:role/test-stg-role",
                "arn:aws:iam::XXXXXXXXXXXX:role/test-dev-role"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/env": "${aws:PrincipalTag/env}"
                }
            }
        }
    ]
}
```

## 3. Parameter storeを作成する

### Parameter store

|name|tag|value|
|---|---|---|
|test-stg|env:stg|任意|
|test-dev|env:dev|任意|

## 4. テスト結果

### 4-1. テスト結果(ロールのスイッチ)

|No|From(User)|To(Role)|Result|
|---|---|---|---|
|1|test-stg|test-stg-role|OK|
|2|test-stg|test-dev-role|NG|
|3|test-dev|test-stg-role|NG|
|4|test-dev|test-dev-role|OK|

#### 1. IAM User: test-stg → Role: test-stg-role

```
$ aws sts assume-role \
> --role-arn arn:aws:iam::XXXXXXXXXXXX:role/test-stg-role \
> --role-session-name my-session \
> --profile test-stg
{
    "Credentials": {
        "AccessKeyId": "XXXXXX",
        "SecretAccessKey": "XXXXXX",
        "SessionToken": "XXXXXX",
        "Expiration": "2020-02-24T09:08:55+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXX:my-session",
        "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/test-stg-role/my-session"
    }
}
```

#### 2. IAM User: test-stg → Role: test-dev-role

```
$ aws sts assume-role \
> --role-arn arn:aws:iam::XXXXXXXXXXXX:role/test-dev-role \
> --role-session-name my-session \
> --profile test-stg
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::XXXXXXXXXXXX:user/test-stg is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/test-dev-role
```

#### 3. IAM User: test-dev → Role: test-stg-role

```
$ aws sts assume-role \
> --role-arn arn:aws:iam::XXXXXXXXXXXX:role/test-stg-role \
> --role-session-name my-session \
> --profile test-dev
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::XXXXXXXXXXXX:user/test-dev is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/test-stg-role
```

#### 4. IAM User: test-dev → Role: test-dev-role

```
$ aws sts assume-role \
> --role-arn arn:aws:iam::XXXXXXXXXXXX:role/test-dev-role \
> --role-session-name my-session \
> --profile test-dev
{
    "Credentials": {
        "AccessKeyId": "XXXXXX",
        "SecretAccessKey": "XXXXXX",
        "SessionToken": "XXXXXX",
        "Expiration": "2020-02-24T09:09:52+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXX:my-session",
        "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/test-dev-role/my-session"
    }
}
```


### 4-2. テスト結果(リソースアクセス)

|No|From(User)|To(Parameter store)|Result|
|---|---|---|---|
|1|test-stg|test-stg|OK|
|2|test-stg|test-dev|NG|
|3|test-dev|test-stg|NG|
|4|test-dev|test-dev|OK|


#### 1. IAM User: test-stg → Parameter Store: test-stg

```
$ aws ssm get-parameter --name test-stg --profile test-stg-role
{
    "Parameter": {
        "Name": "test-stg",
        "Type": "String",
        "Value": "test",
        "Version": 1,
        "LastModifiedDate": "2020-02-24T15:35:40.814000+09:00",
        "ARN": "arn:aws:ssm:us-east-1:XXXXXXXXXXXX:parameter/test-stg"
    }
}
```

#### 2. IAM User: test-stg → Parameter Store: test-dev

```
$ aws ssm get-parameter --name test-dev --profile test-stg-role
An error occurred (AccessDeniedException) when calling the GetParameter operation: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/test-stg-role/botocore-session-XXXXXXXXXX is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-1:XXXXXXXXXXXX:parameter/test-dev
```

#### 3. IAM User: test-dev → Parameter Store: test-stg

```
$ aws ssm get-parameter --name test-stg --profile test-dev-role
An error occurred (AccessDeniedException) when calling the GetParameter operation: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/test-dev-role/botocore-session-XXXXXXXXXX is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-1:XXXXXXXXXXXX:parameter/test-stg
```


#### 4. IAM User: test-dev → Parameter Store: test-dev

```
$ aws ssm get-parameter --name test-dev --profile test-dev-role
{
    "Parameter": {
        "Name": "test-dev",
        "Type": "String",
        "Value": "test",
        "Version": 1,
        "LastModifiedDate": "2020-02-24T15:27:07.440000+09:00",
        "ARN": "arn:aws:ssm:us-east-1:XXXXXXXXXXXX:parameter/test-dev"
    }
}
```

### 感想

- タグに基づく承認が利用できるサービスが少なく、まだまだといった感じです。
    - https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html
- スイッチ先のポリシーでも、スイッチ元のタグから条件判断してスイッチの許可・拒否を判定する条件を記述できればよかったのに。
- aws:RequestTagの概念が難しい。。。