labunix's blog

labunixのラボUnix

AWS Organizationsをawscliで使ってみる。

■AWS Organizationsをawscliで使ってみる。
 マネージメントコンソールなら以下を参照する。

 チュートリアル: 組織の作成と設定
 https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_tutorials_basic.html

 AWS組織を作成
 Consolidated Billing verification complete」の通知メールを確認する。 

 SCPのポリシータイプを有効化
  OUを作成する。
  OUに移動する。

 既存のスタンドアロンアカウントをメンバーとして招待する。
 待された側のアカウントで承認する。
  マネージメントコンソールからロールの切り替えで、                               
  Idとロール名を使ってログインしてみる。

 新規メンバーアカウントを作成する。
 ロールとポリシーを関連付ける。
  マネージメントコンソールからロールの切り替えで、                            
  Idとロール名を使ってログインしてみる


■「leave-organization」は親組織からメンバーアカウントを削除するために、
 退会したいアカウントによって実行するコマンド。
 指定されたアカウントを組織から削除するのは「remove-account-from-organization」
 メンバーから抜けると、スタンドアロンアカウントとして
 請求情報を登録する必要があるので注意。

 awscliのすべてのコマンドとサブコマンドを一覧してみる。
 https://labunix.hateblo.jp/entry/20210117/1610827122

$ awk '/aws organizations [a-z]*-organization$/' aws/subcmd/aws-allsubcmd.txt 
aws organizations create-organization
aws organizations delete-organization
aws organizations describe-organization
aws organizations leave-organization

■招待する側もされる側もrootアカウントを適切に設定し、
 以下2つのAWS管理ポリシーが適用されたIAMユーザで作業出来る。

AdministratorAccess
SystemAdministrator

■まずはAWS組織を作成
 マネージメントコンソールでの「組織の作成」と同じ。
 「ALL」か請求情報に限定した「CONSOLIDATED_BILLING」のどちらかを選択。

$ aws organizations create-organization --feature-set ALL
...[describe-organizationと同じ出力]...

■AWS組織の作成確認

$ aws organizations describe-organization
{
    "Organization": {
        "Id": "o-yyyyyyyyyy",
        "Arn": "arn:aws:organizations::XXXXXXXXXXXX:organization/o-yyyyyyyyyy",
        "FeatureSet": "ALL",
        "MasterAccountArn": "arn:aws:organizations::XXXXXXXXXXXX:account/o-yyyyyyyyyy/XXXXXXXXXXXX",
        "MasterAccountId": "XXXXXXXXXXXX",
        "MasterAccountEmail": "labunix@example.jp",
        "AvailablePolicyTypes": [
            {
                "Type": "SERVICE_CONTROL_POLICY",
                "Status": "ENABLED"
            }
        ]
    }
}

$ aws organizations list-accounts | jq -r '.Accounts[].Status'
ACTIVE

■Consolidated Billing verification complete」の通知メールを確認する。
 メールのリンクからマネージメントコンソールにログインすると確認したことになる。

■既存のスタンドアロンアカウントをメンバーとして招待する。

$ aws organizations invite-account-to-organization \
    --target '{"Type": "EMAIL", "Id": "labunix-sub@example.jp"}' \
    --notes "This is a request for labunix-sub account to join labunix organization."
...[list-handshakes-for-organizationと同じ出力]...

$ aws organizations list-handshakes-for-organization | jq -r '.Handshakes[].State'
OPEN

■招待された側のアカウントで承認する。

$ aws organizations list-handshakes-for-account
...[招待した側のlist-handshakes-for-organizationと同じ出力]...

$ aws organizations accept-handshake \
    --handshake-id $(aws organizations list-handshakes-for-account | jq -r '.Handshakes[].Id')

■招待した側のアカウントで承認状況を確認する。

$ aws organizations list-handshakes-for-organization | jq -r '.Handshakes[].State'
ACCEPTED

■SCPのデフォルトポリシーを確認する。
 ※既存はあるが有効にはなっていない。

$ aws organizations list-policies --filter SERVICE_CONTROL_POLICY | \
    jq -r -c '.Policies[] | [ .Name, .Description ]'
["FullAWSAccess","Allows access to every operation"]

■SCPのポリシータイプを有効化

$ awk '/aws organizations/&&/type/' aws/subcmd/aws-allsubcmd.txt 
aws organizations disable-policy-type
aws organizations enable-policy-type

$ aws organizations enable-policy-type \
    --root-id $(aws organizations list-roots | jq -r '.Roots[].Id') \
    --policy-type SERVICE_CONTROL_POLICY

■OUを作成する。

$ awk '/aws organizations/&&/unit/' aws/subcmd/aws-allsubcmd.txt 
aws organizations create-organizational-unit
aws organizations delete-organizational-unit
aws organizations describe-organizational-unit
aws organizations list-organizational-units-for-parent
aws organizations update-organizational-unit

$ aws organizations create-organizational-unit \
    --parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') \
    --name develop
{
    "OrganizationalUnit": {
        "Id": "ou-XXXX-XXXXXXXX",
        "Arn": "arn:aws:organizations::XXXXXXXXXXXX:ou/o-XXXXXXXXX/ou-XXXX-XXXXXXXX",
        "Name": "develop"
    }
}

■OUに移動する。
 OU=Root直下の招待したアカウントをdevelop配下に移動する。
 招待したアカウントの名前が「labunix」を検索してそのIDを取得している。

$ awk '/aws organizations/&&/account/&&/move/&& !/remove/' aws/subcmd/aws-allsubcmd.txt 
aws organizations move-account

$ aws organizations move-account \
    --account-id $(aws organizations list-accounts | jq -r '.Accounts[] | select (.Name | test ("labunix")) | .Id') \
    --source-parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') \
     --destination-parent-id $(aws organizations list-organizational-units-for-parent --parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') | jq -r '.OrganizationalUnits[].Id')

■Root OUのIDからOUのIDを引いて、そのOUに所属するアカウントの名前を表示
 ※招待された側のアカウント

$ aws organizations list-accounts-for-parent \
    --parent-id $(aws organizations list-organizational-units-for-parent --parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') | jq -r '.OrganizationalUnits[].Id') | \
    jq -r '.Accounts[].Name'
labunix

■Root OUのIDに所属するアカウントの名前を表示
 ※招待した側のアカウント

$ aws organizations list-accounts-for-parent \
    --parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') | jq -r '.Accounts[].Name'
labunix@example.jp

■マネージメントコンソールからロールの切り替えで、
 Idとロール名を使ってログインしてみる。
 ※デフォルトのロール名は「OrganizationAccountAccessRole」

$ aws organizations list-accounts-for-parent \
   --parent-id $(aws organizations list-roots | jq -r '.Roots[].Id') | jq -r '.Accounts[] | select (.Email | test( "labunix-sub@example.jp")) | .Id'
XXXXXXXXXXXX

■新規メンバーアカウントを作成する。

$ awk '/aws organizations/&&/create-account/' aws/subcmd/aws-allsubcmd.txt 
aws organizations create-account
aws organizations describe-create-account-status
aws organizations list-create-account-status

$ aws organizations create-account \
    --email labunix-sub2@example.jp \
    --account-name "product"
{
    "CreateAccountStatus": {
        "Id": "car-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "AccountName": "product",
        "State": "IN_PROGRESS",
        "RequestedTimestamp": "2021-04-16T22:40:12.972000+09:00"
    }
}

$ aws organizations list-create-account-status | jq -r '.CreateAccountStatuses[].State'
SUCCEEDED

$ aws organizations describe-create-account-status \
    --create-account-request-id \
    $(aws organizations list-create-account-status | jq -r '.CreateAccountStatuses[-1].Id') | \
  jq -r '.CreateAccountStatus.State'
SUCCEEDED

■マネージメントコンソールからロールの切り替えで、
 Idとロール名を使ってログインしてみる。
 ※デフォルトのロール名は「OrganizationAccountAccessRole」

$ awk '/aws iam/&& $3 ~ /-role$/&& $3 !~ /instance|service|tag/' aws/subcmd/aws-allsubcmd.txt
aws iam create-role
aws iam delete-role
aws iam get-role
aws iam update-role

$ aws iam list-roles | jq -r '.Roles[] | select( .RoleName | test( "OrganizationAccountAccessRole" ))' | \
    jq -r '.AssumeRolePolicyDocument.Statement' | jq -r '.[].Principal.AWS'
arn:aws:iam::XXXXXXXXXXXX:root

$  aws iam list-roles | jq -r '.Roles[] | select( .RoleName | test( "OrganizationAccountAccessRole" ))'
{
  "Path": "/",
  "RoleName": "OrganizationAccountAccessRole",
  "RoleId": "XXXXXXXXXXXXXXXXXXXXX",
  "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/OrganizationAccountAccessRole",
  "CreateDate": "2021-04-16T14:50:29+00:00",
  "AssumeRolePolicyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
        },
        "Action": "sts:AssumeRole",
        "Condition": {}
      }
    ]
  },
  "MaxSessionDuration": 3600
}

$ aws iam list-attached-role-policies --role-name OrganizationAccountAccessRole
{
    "AttachedPolicies": [
        {
            "PolicyName": "AdministratorAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
        }
    ]
}

$ aws iam list-entities-for-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess | jq -r .
{
  "PolicyGroups": [
    {
      "GroupName": "Admins",
      "GroupId": "XXXXXXXXXXXXXXXXXXXXX"
    }
  ],
  "PolicyUsers": [],
  "PolicyRoles": [
    {
      "RoleName": "OrganizationAccountAccessRole",
      "RoleId": "XXXXXXXXXXXXXXXXXXXXX"
    }
  ]
}