15分で教えるAWSのユーザー管理と権限管理

AWS初めての方にAWSアカウントとIAMを説明する用の記事です。

短い時間で全体像を把握してもらうことを目的としているため、これを読んだところでAWSの設定ができるようにはなりません。自分が使っている環境をベースに書いているので、人によっては足りない部分があると思います。

初めから詳しく知りたい場合はBlackBeltを見ることをおすすめします。
[AWS Black Belt Techシリーズ AWS IAM](https://www.slideshare.net/AmazonWebServicesJapan/20150617-aws-blackbeltiam)

# この記事の目的

* AWSコンソールへの認証、ログイン方法になにがあるか知ってもらう
* AWSサービスの認可、権限をどう管理しているのか知ってもらう
* AWSアカウントの分け方と関係性はどうなっているか知ってもらう
* AWS管理者が不安に思いそうなところを先んじて抑える


# AWSコンソールへのログイン方法

コンソールへのログインに用いるユーザーは主に３種類あります。

* AWSルートユーザー（ID/Password）
* IAMユーザー（ID/Password）
* フェデレーションユーザー（SAML等）

参考：[ID 管理の概要: ユーザー \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/introduction_identity-management.html)
参考：[ID（ユーザー、グループ、ロール） \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id.html)

## AWSルートユーザー

AWSアカウント作成時に登録したメールアドレスでログインするとルートユーザーになります。
ルートユーザーはすべての操作をすることができます。

ルートユーザーはその特性上、アカウントの設定で挙動を縛ることはほぼ不可能なため（OrganizationのService Control Policyなら可能）、組織で使う場合ルートユーザーを利用者に使わせることはほぼありません。
管理者でも使うことはめったになく、MFA登録して塩漬けすることが多いです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/135041/278ae8e8-6e97-4535-5f2b-44418c80cc12.png" alt="rootuser_mfa.png" width="400px">

ただしルートユーザーでしかできないこともあるため、MFA登録しておいて登録端末を破棄するなどといった自爆技で完全に使えないようにしてはいけません。

参考：[AWS アカウントのルートユーザー が必要な AWS タスク \- アマゾン ウェブ サービス](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_tasks-that-require-root.html)

## IAMユーザー

IAM(Identity and Access Management)というAWSのサービスを用いると、２種類のユーザーが作成できます。

* コンソール利用可能IAMユーザー（人によるGUI操作向け）
* コンソール利用不可IAMユーザー（プログラムからの操作向け）

AWSアカウント数が少なければコンソール利用可能なIAMユーザーを使うのが一般的です。

![iam-user.png](https://qiita-image-store.s3.amazonaws.com/0/135041/9df3a0a0-3a15-e32d-a34f-071c6edb4a90.png)

AWSアカウント数が多いときは、IAMユーザーをアカウントごとに作り管理する手間を削減するため、フェデレーションユーザーを使う場合が多いと思います。

## フェデレーションユーザー

自組織内の認証基盤などを用いてSAML認証でAWSにログインすることができます。
フェデレーションログインの場合は事前に定めた権限（IAMロール）の一時的セキュリティ認証情報を発行してログインします。

これだとひとりひとりにIAMユーザーを作る必要がありません。
AWSからは `IAMロール名/Idp認証時のユーザーID` といったユーザーとして認識されます。
ex. `S3ReadOnlyRole/hogehoge@example.com`

<img src="https://qiita-image-store.s3.amazonaws.com/0/135041/91f35587-edd7-8037-3f77-588a8140cf28.png" alt="federation-user.png" width="400px" />



Idpを含めた認証フローは公式がわかりやすいので割愛。

![saml-based-sso-to-console.diagram.png](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/images/saml-based-sso-to-console.diagram.png)

参考：[SAML 2\.0 フェデレーションユーザーが AWS マネジメントコンソールにアクセス可能にする \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_enable-console-saml.html)



# AWS APIの利用方法

APIの利用方法は主に２種類あります。

* IAMユーザーのアクセスキー
* IAMロールの一時的セキュリティ認証情報

## IAMユーザーのアクセスキー

IAMユーザーはAPIを利用できるアクセスキーを発行できます。
AWS外からAWSのAPIを利用したい時は、このアクセスキーを使います。

![iam-user.png](https://qiita-image-store.s3.amazonaws.com/0/135041/9df3a0a0-3a15-e32d-a34f-071c6edb4a90.png)

AWS内のリソースからAPIを利用したい場合はアクセスキーを使わずに、IAMロールを使うことが推奨されています。

## IAMロールの一時的セキュリティ認証情報

IAMロールは権限の塊としての役割以外に、一時的セキュリティ認証情報を発行してサービスやフェデレーションユーザーやEC2などに権限を与えることができます。

![sts_assumerole.png](https://qiita-image-store.s3.amazonaws.com/0/135041/3ca51d65-a2a4-8d3c-1454-eea190843d9e.png)

一時的セキュリティ認証情報といっていますが、これもアクセスキーです。
IAMユーザーのアクセスキーとは違い、有効期限ありのアクセスキーになります。
`DurationSeconds` パラメータで認証情報の有効期限を設定できます。
デフォルト１時間で最大１２時間まで延ばすことができます。

アクセスキーを都度発行するため、サービスにアクセスキーを埋め込む必要がなくセキュアに使えます。

```shell
# 割り当てRoleの確認
$ aws sts get-caller-identity
# インスタンスプロファイルの確認
$ curl http://169.254.169.254/latest/meta-data/iam/info
# Default region / output は初期値として未設定なので必要なら設定する、アクセスキー部分は空白でOK
$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: ap-northeast-1
Default output format [None]: json
```


参考：[ロールの一般的なシナリオ: ユーザー、アプリケーション、およびサービス \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_common-scenarios.html)
参考：[一時的セキュリティ認証情報 \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_temp.html)

# AWSサービスの認可、権限管理方法

すでに用語としては何度も出してしまっていますが、権限管理で使っている機能についてちゃんと説明します。

## IAMポリシー

AWSの権限管理の最小単位はIAMポリシーと呼ばれていて、権限をjsonで管理しています。
IAMポリシーはIAMユーザー・グループ・ロールにアタッチできます。

![policy_attach.jpg](https://image.slidesharecdn.com/003securityidentityandaccessmanagement-161115000017/95/awsome-day-2016-module-3-security-identity-and-access-management-19-638.jpg?cb=1479168254)

参考：[AWSome Day 2016 \- Module 3: Security, Identity, and Access Management](https://www.slideshare.net/AmazonWebServices/awsome-day-2016-module-3-security-identity-and-access-management)

IAMポリシーは以下のような構造となっており、`Condition:どういう条件のとき`　`Action:どのサービスのどのアクション` を `Resource:どのリソース` に対して `Effect:許可・拒否` するかを設定することができます。

* `Effect` – ポリシーがアクセスを許可または拒否するかどうか
* `Action` – ポリシーによって許可または拒否されるアクションのリスト
* `Resource` – アクションを起こすことができるリソースのリスト
* `Condition` (オプション) – ポリシーがアクセス許可を付与する状況

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-west-1:123456789012:table/myDynamoTable"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${cognito-identity.amazonaws.com:sub}"
                    ]
                }
            }
        }
    ]
}
```

参考：[IAM ポリシー \- AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html)

## IAMロール

IAMユーザーが使う場合、IAMポシリーはIAMロールにまとめてIAMグループにアタッチするのが一般的です。
IAMユーザーはIAMグループに所属させることで権限を得るような管理になります。
サービスで使う場合、同じくIAMロールにまとめて、それをそのまま使います。

<img src="https://qiita-image-store.s3.amazonaws.com/0/135041/8054a9de-8ede-fb90-4bab-a76239f0f606.png" alt="iam-group" width="400px">


この図のようにIAMロールは権限の塊として認識しておけばいいのですが、ほかにもIAMロールは役割があります。
それが先に何度も出てきた一時的セキュリティ認証情報の付与になります。

すべてのIAMロールで一時的セキュリティ認証情報を発行できるわけではなく、`Principal:どのサービスorアカウントから` であれば `Action:一時的セキュリティ認証情報の発行` が `Effect:可能`　かもポリシーで制御可能です。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": [ "123456789012" ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```