AWS OrganizationsをAWS CLIでひととおり操作してみた

ひととおり操作してみました。

アカウント作成が簡単になるので非常に助かる。

# 注意点

* エンドポイントは"us-east-1"のみ
* アカウント作成時に必要な権限や作成したアカウントの削除可否など、いくつか注意点があるのでドキュメントをよく読みましょう。
    * [Creating an AWS Account in Your Organization](http://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_accounts_create.html)

# 準備作業

## リージョンの指定

```bash:command
export AWS_DEFAULT_REGION="us-east-1"
```

# Organizationの作成

## Organizationの作成

```bash:command
aws organizations create-organization \
    --feature-set ALL
```

```json:result
{
    "Organization": {
        "AvailablePolicyTypes": [
            {
                "Status": "ENABLED",
                "Type": "SERVICE_CONTROL_POLICY"
            }
        ],
        "MasterAccountId": "************",
        "MasterAccountArn": "arn:aws:organizations::************:account/o-**********/************",
        "FeatureSet": "ALL",
        "MasterAccountEmail": "********@*******.jp",
        "Id": "o-**********",
        "Arn": "arn:aws:organizations::************:organization/o-**********"
    }
}
```

## Organizationの確認

```bash:command
aws organizations describe-organization
```

```json:result
{
    "Organization": {
        "AvailablePolicyTypes": [
            {
                "Status": "ENABLED",
                "Type": "SERVICE_CONTROL_POLICY"
            }
        ],
        "MasterAccountId": "************",
        "MasterAccountArn": "arn:aws:organizations::************:account/o-**********/************",
        "FeatureSet": "ALL",
        "MasterAccountEmail": "********@*******.jp",
        "Id": "o-**********",
        "Arn": "arn:aws:organizations::************:organization/o-**********"
    }
}
```

## Root Accountの確認

```bash:command
aws organizations list-roots
```

```json:result
{
    "Roots": [
        {
            "PolicyTypes": [],
            "Id": "r-****",
            "Arn": "arn:aws:organizations::************:root/o-**********/r-****",
            "Name": "Root"
        }
    ]
}
```


# Organization Unit（以下、OU）の作成

## Root AccountのIDを取得

```bash:command
ROOT_ID=$(aws organizations list-roots \
    --query Roots[].Id \
    --output text) \
    && echo ${ROOT_ID}
```

```text:result
r-****
```

## OU名の指定

```bash:command
OU_NAME="test-ou"
```

## OUの作成

```bash:command
aws organizations create-organizational-unit \
    --parent-id ${ROOT_ID} \
    --name ${OU_NAME}
```

```json:result
{
    "OrganizationalUnit": {
        "Id": "ou-****-********",
        "Arn": "arn:aws:organizations::************:ou/o-**********/ou-****-********",
        "Name": "test-ou"
    }
}
```

## OUの確認

### OUのIDを取得

```bash:command
OU_ID=$(aws organizations list-organizational-units-for-parent \
    --parent-id ${ROOT_ID} \
    --query OrganizationalUnits[].Id \
    --output text) \
    && echo ${OU_ID}
```

```text:result
ou-****-********
```


### OUの確認

```bash:command
aws organizations describe-organizational-unit \
    --organizational-unit-id ${OU_ID}
```

```json:result
{
    "OrganizationalUnit": {
        "Id": "ou-****-********",
        "Arn": "arn:aws:organizations::************:ou/o-**********/ou-****-********",
        "Name": "test-ou"
    }
}
```


# Policyの作成

## Policyの作成

### Policy Documentのファイル名を指定

```bash:command
POLICY_FILE_NAME="scp.json"
```

### Policy Documentの生成

```bash:command
cat << EOF > ${POLICY_FILE_NAME}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudtrail:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "config:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "aws-portal:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "budgets:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sts:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
EOF
```

### Policy Documentの確認

```bash:command
cat ${POLICY_FILE_NAME}
```

### Policy Documentの検証

```bash:command
jsonlint -q ${POLICY_FILE_NAME}
```

### Policy名の指定

```bash:command
POLICY_NAME="test-policy"
POLICY_DESCRIPTION="This is test policy."
```

### Policyの作成

```bash:command
aws organizations create-policy \
    --content file://${POLICY_FILE_NAME} \
    --description "${POLICY_DESCRIPTION}" \
    --name ${POLICY_NAME} \
    --type SERVICE_CONTROL_POLICY
```

```json:result
{
    "Policy": {
        "Content": "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iam:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"cloudtrail:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"config:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"aws-portal:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"budgets:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"s3:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"sns:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"sts:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
        "PolicySummary": {
            "AwsManaged": false,
            "Description": "This is test policy.",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-********",
            "Arn": "arn:aws:organizations::************:policy/o-**********/service_control_policy/p-********",
            "Name": "test-policy"
        }
    }
}
```

## Policyの確認

### Policyの一覧

```bash:command
aws organizations list-policies \
    --filter SERVICE_CONTROL_POLICY
```

```json:result
{
    "Policies": [
        {
            "AwsManaged": true,
            "Description": "Allows access to every operation",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-FullAWSAccess",
            "Arn": "arn:aws:organizations::aws:policy/service_control_policy/p-FullAWSAccess",
            "Name": "FullAWSAccess"
        },
        {
            "AwsManaged": false,
            "Description": "This is test policy.",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-********",
            "Arn": "arn:aws:organizations::************:policy/o-**********/service_control_policy/p-********",
            "Name": "test-policy"
        }
    ]
}
```

### Policyの詳細を表示

```bash:command
POLICY_ID=$(aws organizations list-policies \
    --filter SERVICE_CONTROL_POLICY \
    --query Policies[?Name==\`${POLICY_NAME}\`].Id \
    --output text) \
    && echo ${POLICY_ID}
```

```text:result
p-********
```

```bash:command
aws organizations describe-policy \
    --policy-id ${POLICY_ID}
```

```json:result
{
    "Policy": {
        "Content": "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iam:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"cloudtrail:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"config:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"aws-portal:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"budgets:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"s3:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"sns:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"sts:*\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
        "PolicySummary": {
            "AwsManaged": false,
            "Description": "This is test policy.",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-********",
            "Arn": "arn:aws:organizations::************:policy/o-**********/service_control_policy/p-********",
            "Name": "test-policy"
        }
    }
}
```


# Policyの適用

## アタッチされているPolicyを確認

```bash:command
aws organizations list-policies-for-target \
    --target-id ${OU_ID} \
    --filter SERVICE_CONTROL_POLICY
```

```json:result
{
    "Policies": [
        {
            "AwsManaged": true,
            "Description": "Allows access to every operation",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-FullAWSAccess",
            "Arn": "arn:aws:organizations::aws:policy/service_control_policy/p-FullAWSAccess",
            "Name": "FullAWSAccess"
        }
    ]
}
```


## Policy Typeの有効化（？）

```bash:command
aws organizations enable-policy-type \
    --root-id ${ROOT_ID} \
    --policy-type SERVICE_CONTROL_POLICY
```

```json:result
{
    "Root": {
        "PolicyTypes": [],
        "Id": "r-****",
        "Arn": "arn:aws:organizations::************:root/o-**********/r-****",
        "Name": "Root"
    }
}
```

## PolicyをOUにアタッチ

```bash:command
aws organizations attach-policy \
    --policy-id ${POLICY_ID} \
    --target-id ${OU_ID}
```

```text:result
（返値無し）
```

## Policyがアタッチされたことを確認

```bash:command
aws organizations list-policies-for-target \
    --target-id ${OU_ID} \
    --filter SERVICE_CONTROL_POLICY
```

```json:result
{
    "Policies": [
        {
            "AwsManaged": true,
            "Description": "Allows access to every operation",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-FullAWSAccess",
            "Arn": "arn:aws:organizations::aws:policy/service_control_policy/p-FullAWSAccess",
            "Name": "FullAWSAccess"
        },
        {
            "AwsManaged": false,
            "Description": "This is test policy.",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-********",
            "Arn": "arn:aws:organizations::************:policy/o-**********/service_control_policy/p-********",
            "Name": "test-policy"
        }
    ]
}
```

## 既存のPolicyのデタッチ

```bash:command
aws organizations detach-policy \
    --policy-id "p-FullAWSAccess" \
    --target-id ${OU_ID}
```

```text:result
（返値無し）
```


## Policyがデタッチされたことを確認

```bash:command
aws organizations list-policies-for-target \
    --target-id ${OU_ID} \
    --filter SERVICE_CONTROL_POLICY
```

```json:result
{
    "Policies": [
        {
            "AwsManaged": false,
            "Description": "This is test policy.",
            "Type": "SERVICE_CONTROL_POLICY",
            "Id": "p-********",
            "Arn": "arn:aws:organizations::************:policy/o-**********/service_control_policy/p-********",
            "Name": "test-policy"
        }
    ]
}
```

# Accountの作成

```bash:command
EMAIL="***@***.jp"
ACCOUNT_NAME="test-account"
```

```bash:command
aws organizations create-account \
    --email ${EMAIL} \
    --account-name ${ACCOUNT_NAME} \
    --iam-user-access-to-billing ALLOW
```

```json:result
{
    "CreateAccountStatus": {
        "RequestedTimestamp": 1488639507.841,
        "State": "IN_PROGRESS",
        "Id": "car-********************************",
        "AccountName": "test-account"
    }
}
```

```bash:command
aws organizations describe-create-account-status \
    --create-account-request-id car-********************************
```

```json:result
{
    "CreateAccountStatus": {
        "AccountName": "test-account",
        "State": "SUCCEEDED",
        "RequestedTimestamp": 1488639508.084,
        "CompletedTimestamp": 1488639513.734,
        "Id": "car-********************************",
        "AccountId": "************"
    }
}
```

```bash:command
aws organizations list-accounts
```

```json:result
{
    "Accounts": [
        {
            "Status": "ACTIVE",
            "Name": "test-account",
            "JoinedMethod": "CREATED",
            "JoinedTimestamp": 1488639510.79,
            "Id": "************",
            "Arn": "arn:aws:organizations::************:account/o-**********/************"
        },
        {
            "Status": "ACTIVE",
            "Name": "Nobuhiro Nakayama",
            "JoinedMethod": "INVITED",
            "JoinedTimestamp": 1488633570.287,
            "Id": "************",
            "Arn": "arn:aws:organizations::************:account/o-**********/************"
        }
    ]
}
```

```bash:command
ACCOUNT_ID=$(aws organizations list-accounts \
    --query Accounts[?Name==\`${ACCOUNT_NAME}\`].Id \
    --output text) \
    && echo ${ACCOUNT_ID}
```


```bash:command
aws organizations describe-account \
    --account-id ${ACCOUNT_ID}
```

```json:result
{
    "Account": {
        "Status": "ACTIVE",
        "Name": "test-account",
        "JoinedMethod": "CREATED",
        "JoinedTimestamp": 1488639510.79,
        "Id": "************",
        "Arn": "arn:aws:organizations::************:account/o-**********/************"
    }
}
```


# AccountをOUに移動

## Account移動前の親リソースを確認

Account作成直後はRoot配下になることが確認できます。

```bash:command
aws organizations list-parents \
    --child-id ${ACCOUNT_ID}
```

```json:result
{
    "Parents": [
        {
            "Type": "ROOT",
            "Id": "r-****"
        }
    ]
}
```

## Accountの移動

```bash:command
aws organizations move-account \
    --account-id ${ACCOUNT_ID} \
    --source-parent-id ${ROOT_ID} \
    --destination-parent-id ${OU_ID}
```

```text:result
（返値無し）
```

## Account移動後の親リソースを確認

```bash:command
aws organizations list-parents \
    --child-id ${ACCOUNT_ID}
```

```json:result
{
    "Parents": [
        {
            "Type": "ORGANIZATIONAL_UNIT",
            "Id": "ou-****-********"
        }
    ]
}
```

# （動作確認）作成したAccountにアクセス

デフォルトでは"OrganizationAccountAccessRole"というRoleが作成されているため、このRoleにAssume Roleします。

```bash:command
aws sts assume-role \
    --role-arn "arn:aws:iam::${ACCOUNT_ID}:role/OrganizationAccountAccessRole" \
    --role-session-name "test-session"
```

```json:result
{
    "AssumedRoleUser": {
        "AssumedRoleId": "A********************:test-session",
        "Arn": "arn:aws:sts::************:assumed-role/OrganizationAccountAccessRole/test-session"
    },
    "Credentials": {
        "SecretAccessKey": "****************************************",
        "SessionToken": "****************************************************************************************************************************************************************************************************************************************************************************************************************************************************",
        "Expiration": "2017-03-04T16:37:55Z",
        "AccessKeyId": "********************"
    }
}
```


以上