[JAWS-UG CLI] AWS Organizations 入門 (4) アカウントの作成およびOUへの移動

# この記事について

[JAWS-UG CLI専門支部 #83 Organizations入門](https://jawsug-cli.doorkeeper.jp/events/57578)で実施するハンズオン用の手順書です。


# 前提条件

## 必要な権限

- Organizationsのフルコントロール権限
- Identity and Access Managementのフルコントロール権限
- Security Token Serviceのフルコントロール権限


## 必要なリソース

**本日のハンズオンは、親アカウントの作成と削除も含めて実施します**

- メールアドレス × 2（親アカウントおよび子アカウント用）
- クレジットカード情報
- 通話可能な電話番号（個人認証用）

# 0. 準備

## 0.1. リージョンを指定

AWS Organizatonsのリージョンは、バージニアリージョンのみで提供されています。

```bash:コマンド
export AWS_DEFAULT_REGION="us-east-1"
```

## 0.2. 資格情報を確認

```bash:コマンド
aws configure list
```

```text:結果（例）
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                  aws-org           manual    --profile
access_key     ****************6TOQ shared-credentials-file
secret_key     ****************EtJQ shared-credentials-file
    region                us-east-1              env    AWS_DEFAULT_REGION
```

## 0.3. バージョン確認

```bash:コマンド
aws --version
```

```text:結果
aws-cli/1.11.80 Python/2.7.12 Linux/4.9.20-10.30.amzn1.x86_64 botocore/1.5.43
```

## 0.4. バージョンアップ（必要に応じて）

```bash:コマンド
sudo pip install -U awscli
```

# 1. Accountの作成

## 1.1. Accountの作成

### メールアドレスおよびアカウント名の指定

```bash:コマンド
EMAIL="***@***.jp"
ACCOUNT_NAME="test-account"
```

### アカウントの作成

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

```json:結果
{
    "CreateAccountStatus": {
        "RequestedTimestamp": 1493025376.947,
        "State": "IN_PROGRESS",
        "Id": "car-abcc5ac028ce11e799da500c04b7b2c5",
        "AccountName": "test-account"
    }
}
```

### アカウント作成の進捗を確認

作成が完了すると、アカウントに設定したメールアドレスにアカウント作成が完了した旨のメールが送付されます。

```bash:コマンド
STATUS_ID=$(aws organizations list-create-account-status \
    --query "CreateAccountStatuses[?AccountName==\`${ACCOUNT_NAME}\`].Id" \
    --output text) \
    && echo ${STATUS_ID}
```

```bash:コマンド
aws organizations describe-create-account-status \
    --create-account-request-id ${STATUS_ID}
```

```json:結果
{
    "CreateAccountStatus": {
        "AccountName": "test-account",
        "State": "SUCCEEDED",
        "RequestedTimestamp": 1493025377.308,
        "CompletedTimestamp": 1493025385.25,
        "Id": "car-abcc5ac028ce11e799da500c04b7b2c5",
        "AccountId": "642906553190"
    }
}
```

### アカウントが作成されたことを確認

```bash:コマンド
aws organizations list-accounts
```

```json:結果
{
    "Accounts": [
        {
            "Status": "ACTIVE",
            "Name": "Nobuhiro Nakayama",
            "JoinedMethod": "INVITED",
            "JoinedTimestamp": 1493008453.5,
            "Id": "************",
            "Arn": "arn:aws:organizations::************:account/o-0vapyd2tob/************"
        },
        {
            "Status": "ACTIVE",
            "JoinedMethod": "CREATED",
            "JoinedTimestamp": 1493025383.162,
            "Id": "XXXXXXXXXXXX",
            "Arn": "arn:aws:organizations::************:account/o-0vapyd2tob/XXXXXXXXXXXX"
        }
    ]
}
```

### 作成したアカウントの詳細を確認

```bash:コマンド
ACCOUNT_ID=$(aws organizations list-create-account-status \
    --query "CreateAccountStatuses[?AccountName==\`${ACCOUNT_NAME}\`].AccountId" \
    --output text) \
    && echo ${ACCOUNT_ID}
```

```bash:コマンド
aws organizations describe-account \
    --account-id ${ACCOUNT_ID}
```

```json:結果
{
    "Account": {
        "Status": "ACTIVE",
        "Name": "test-account",
        "JoinedMethod": "CREATED",
        "JoinedTimestamp": 1493025383.162,
        "Id": "XXXXXXXXXXXX",
        "Arn": "arn:aws:organizations::************:account/o-0vapyd2tob/XXXXXXXXXXXX"
    }
}
```


# 2. AccountをOUに移動

先に作成したOUにアカウントを移動します。

## 2.1. AccountをOUに移動

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

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

```bash:コマンド
aws organizations list-parents \
    --child-id ${ACCOUNT_ID}
```

```json:結果
{
    "Parents": [
        {
            "Type": "ROOT",
            "Id": "r-e2uv"
        }
    ]
}
```

### Accountの移動

```bash:コマンド
aws organizations move-account \
    --account-id ${ACCOUNT_ID} \
    --source-parent-id ${ROOT_ID} \
    --destination-parent-id ${OU_ID}
```

```text:結果
（返値無し）
```

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

```bash:コマンド
aws organizations list-parents \
    --child-id ${ACCOUNT_ID}
```

```json:結果
{
    "Parents": [
        {
            "Type": "ORGANIZATIONAL_UNIT",
            "Id": "ou-e2uv-0w028u9k"
        }
    ]
}
```

# 3. 動作確認

## 3.1. Assume Roleによる認証情報の取得

### 認証情報の取得

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

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

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

### 認証情報を環境変数に格納

```bash:コマンド
export AWS_ACCESS_KEY_ID=XXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXX
export AWS_SESSION_TOKEN=XXXXXXXXXXXXXXXX
```

```bash:コマンド
aws configure list
```

```text:結果
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                  aws-org           manual    --profile
access_key     ****************F5VQ              env
secret_key     ****************AYXL              env
    region                us-east-1              env    AWS_DEFAULT_REGION
```

## 3.2. 動作確認

### 許可したアクションを実行できることを確認

EC2のAPIを呼び出します。

```bash:コマンド
aws ec2 describe-instances
```

```json:結果
{
    "Reservations": []
}
```


### 許可していないアクションが実行できないことを確認

RDSのAPIを呼び出します。

```bash:コマンド
aws rds describe-db-instances
```

```text:結果
An error occurred (AccessDenied) when calling the DescribeDBInstances operation: User: arn:aws:sts::642906553190:assumed-role/OrganizationAccountAccessRole/test-session is not authorized to perform: rds:DescribeDBInstances
```

### 作成したアカウントのロールを確認

```bash:コマンド
aws iam list-roles
```

```json:結果
{
    "Roles": [
        {
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Action": "sts:AssumeRole",
                        "Effect": "Allow",
                        "Principal": {
                            "AWS": "arn:aws:iam::************:root"
                        }
                    }
                ]
            },
            "RoleId": "AROAIR4DS2TGGFYOWAILG",
            "CreateDate": "2017-04-24T09:16:21Z",
            "RoleName": "OrganizationAccountAccessRole",
            "Path": "/",
            "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/OrganizationAccountAccessRole"
        }
    ]
}
```

### 既存のIAMロールにアタッチされているポリシーを確認

```bash:コマンド
aws iam list-role-policies --role-name OrganizationAccountAccessRole
```

```json:結果
{
    "PolicyNames": [
        "AdministratorAccess"
    ]
}
```


以上