AWS再入門ブログリレー AWS Identity and Access Management (IAM)編

当エントリは弊社コンサルティング部による『AWS 再入門ブログリレー 2019』の7日目のエントリです。

このブログリレーの企画は、普段AWSサービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。

AWSをこれから学ぼう!という方にとっては文字通りの入門記事として、またすでにAWSを活用されている方にとってもAWSサービスの再発見や2019年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。

では、さっそくいってみましょう。7日目のテーマは『AWS Identity and Access Management (IAM)』です。

目次

IAMとは

AWS Identity and Access Management (IAM)はAWSリソースに対してのセキュアなアクセス制御をするためのAWSサービスです。 IAM ユーザーやIAM グループ、IAM ロールまたIAM ポリシーを用いて認証と認可を行います。 SAML認証を使用したSSOの実現や、MFAにも対応しており非常に柔軟でセキュアなサービスとなっています。

IAMはAWSのユーザは誰でも使用するようなサービスで非常に便利なのですが、少しややこしいのでなんとなくで理解して使ってる人もいると思います。 これを機にIAMの各種コンポーネントや仕組みを理解していただいてよりIAMに寄り添ってくれれば幸いです。

認証と認可について

IAMについて書く前にIAMを理解する上で非常に大事な内容である、認証と認可についておさらいしましょう。

認証

英語で認証は、Authenticateといい、辞書で意味を調べると、「何かが本物であることを証明すること」と書いてあります。 ざっくりと言うと、相手が誰であるかを確認することです。

例えば私が本当に「奥」であることを示すために、あなたに免許証を見せたとします。 あなたは私が本人であることを確認できるでしょうが、それ以上の意味はあるでしょうか。

伝えたいポイントは2つです。 認証のためには認証情報が必要であることと、認証だけでは何もできないということです。

認可

英語で認可はAuthorizationといい、辞書で意味を調べると、「何かをするための公式の許可または、公式の許可を与えること」と書いてあります。 ざっくり言うと、何かをするための権限を与えることです。

電車に乗ることを例にとって考えます。 私たちは電車の切符を買えば誰でも電車に乗ることができます。 たとえあなたの友人がまとめて切符を買ってそれをあなたに渡したとしても何も問題なく電車に乗ることができます。 が切符を買ったかに関わらず切符を持っている状態、すなわち認可がおりていれば問題なく行動を起こせます。

ですが、一方で切符を持っていても電車の運転はさせてくれませんよね。 電車に乗るという行動の範囲を超えたことはできません、すなわち認可されたからといって全ての権限が付与されるとは限られません。

伝えたいポイントは2つです。 認可がおりると権限の範疇で行動を起こせることと、認証と認可は別物ということです。

認証と認可のフロー

ざっくりこんな感じのフローを書いてみました。

これを一般的なWebアプリケーションと捉えると下記のような流れで、認証と認可が進んでいきます。 もちろん本当はもっと複雑です。

  1. ユーザがIDとパスワードを入力して送信する
  2. 認証するところでこのユーザが本当に存在してかつ、正しい認証情報かを調べる
    1. 問題なければ認可するところにユーザ情報を渡す
    2. 問題があればエラーを返す
  3. 認可するところでこのユーザが実行するアクションに対して権限を持ってるかを調べる
    1. 問題なければアクションを実行する
    2. 問題があればエラーを返す
  4. 実際に実行して結果を返す

少しだけ余談をさせてください。 なんで認証と認可ってごちゃごちゃになりやすいんでしょうか。個人的にはこう思っています。

  • 認証と認可は非常に密な関係であることが多い
  • ユーザにとって認可は隠蔽されている部分なので認知しづらい

また認証と認可についてもっと詳しく知りたい方はこちらのブログをみてください。

よくわかる認証と認可

IAMの仕組み

前置きが長くなってしまいましたが、本題に入っていきましょう。 最初にIAMの仕組みを少し説明します。 そのあとにIAMのコンポーネントについて理解していくことできっとIAMと仲良くなれます。

まずはこちらの図をみてください。

認証と認可の説明の際に見せた図と似てますね。 プリンシパル(先ほどのユーザの部分)の部分にIAM ユーザーとIAM ロールがあり、認可の部分にIAM Policyを置いています。 あのフローと交互に見比べるとなんとなくIAMの基本的な役割がわかるのではないでしょうか。

IAM ユーザーとグループ、ロールそしてIAM ポリシーについてまずは理解を深めていきましょう。

IAM ユーザー

AWSサービスへのアクセスを行うためのユーザや、アプリケーションのことをさします。

アクセスの種類(認証情報のパターン)

AWSサービスへのアクセスを行うパターンとしてマネジメントコンソールへのアクセスと、API呼び出しの2種類が挙げられます。IAM ユーザーではこの2つのパターンで認証情報が異なります。

  • プログラムによるアクセス

識別子としてアクセスキーIDを、認証情報として、シークレットアクセスキーを使用します。 ざっくりこの2つの組み合わせなら、プログラムによるアクセスができるという認識で問題ありません。 AWS CLIや各種SDK、直接のAPIコールの際にはこちらを使用します。 また追加の認証情報としてMFAトークンを使用することもできます。

  • AWSマネジメントコンソールへのアクセス

識別子として名前を、認証情報として、パスワードを使用します。 ざっくりこの2つの組み合わせなら、マネジメントコンソールによるアクセスができるという認識で問題ありません。 また追加の認証情報としてMFAトークンを使用することもできます。 そして、IAM ユーザーではパスワードをどれだけ複雑にする必要があるかや、パスワードの更新期間をパスワードポリシーを使用して指定できます。 詳しくはこちらのドキュメントに設定できるポリシーが記述されています。

IAM ポリシー

IAM ユーザーについては理解できましたか。あくまでもIAM ユーザーは認証のためのものです。
IAM ユーザーを作るだけではAWSリソースへの操作は何もできません。なので権限を付与する必要があります。 そのために使用するのが、IAM ポリシーです。

IAMポリシーでは2つのことを行います。 1つ目はユーザが実施すること、すなわち私たちがすることで誰がどのリソースにアクセスできるかという権限を定義します。 2つ目はAWS側が行うことで、AWSリソースへのリクエストを評価して権限がある場合にのみアクションを行います。

AWS側でどのような操作を行なっているかは置いといて、私たちがするべきことは権限の定義のみです。 IAMではJSON形式で書かれたポリシー言語を元にポリシーを作成します。 ポリシー言語にはEffectとPrincipal、Action、Resources、Conditionで構成されており、それぞれの頭文字をとってPARCモデルといったりもしています。 言葉だけだと説明しにくいので実際にありそうなポリシーをみてみましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement",
      "Effect": "Allow",
      "Action": [ "s3:Get*" ],
      "Resource": [
        "arn:aws:s3:::confidential-data",
        "arn:aws:s3:::confidential-data/*"
      ],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    }
  ]
}

このポリシーは、MFAが有効になっている場合に、confidential-dataというS3バケットの中のオブジェクトを取得できるポリシーです。

ポリシーの構成要素をもう一度確認しましょう。

名前 説明
Version ポリシー言語のバージョン 2008-10-17と2012-10-17があるが、2012-10-17しか使わない
Statement この中にステートメントを書いていく 必須
Sid ポリシードキュメントに与える任意の識別子 JSONの中で一意である必要がある
Effect ステートメントの結果を拒否するか許可するかを書く AllowDenyのみ許可される 必須
Principal AWSサービスへのリソースが許可、または拒否されるIAM ユーザーやグループ、ロールなどを書く
Action 許可または拒否される特定のアクション サービス名:アクションと言う形でだいたい書かれる
Resource ステートメントで扱うAWSリソース ${aws:username}のような形で変数などもしようできる
Condition 権限を付与できる条件を指定する 例で出したMFAの有無の他にも時間とかIPアドレスとか色々な方法で制限できる

ポリシーは基本的にIAM ユーザーやグループ、ロールにアタッチするため、暗黙的にプリンシパルが決定されるので、プリンシパルはあまり使いません。 プリンシパルを使用する場面はS3バケットやKMS CMKなどといったAWSリソースにポリシーをアタッチする場合に使用されます。 このAWSリソースに対してアタッチするポリシーのことをリソースベースのポリシーと言い、IAM ユーザーやグループ、ロールにアタッチするポリシーのことをアイデンティティベースのポリシーと呼びます。

アイデンティティベースのポリシーの場合はポリシーを作って満足してはいけません。
IAM ユーザーで認証をしてIAM ポリシーで認可を行いますが、両者が紐づいてはいません。
なのでIAM ユーザーに対して必要なポリシーをアタッチしましょう。

ポリシーの種類管理ポリシーとインラインポリシー

アイデンティティベースのポリシーを設定する場合は下記の3種類から選んで使用します。

  • AWS 管理ポリシー

IAM ユーザー作成時にAdministratorAccessや、PowerUserAccessといったポリシーをみたことはあるでしょう。
これらのようにAWSが作成および管理するスタンドアロンポリシー(独自のARNが付いたポリシー)のことをAWS 管理ポリシーと呼びます。
多くのユースケースに対応できるようにたくさんの管理ポリシーがあるのでポリシー使う場合にはまず第一に使用を検討することをお勧めします。

  • カスタマー管理ポリシー

各々のユーザアカウントで管理できるスタンドアロンのポリシーのことを指します。
なので、自分で作ったポリシーがこれに該当します。

  • インラインポリシー

プリンシパルエンティティ(IAM ユーザー、グループ、またはロール)に対して直接埋め込むポリシーです。
基本的には使いませんが、エンティティとポリシーを厳密に1対1で紐付ける場合のみ使用します。
プリンシパルエンティティに対して意図しないポリシーのアタッチを確実に防ぐというユースケースぐらいしか私には思いつきません。

IAM グループ

複数のIAM ユーザーに対して毎回IAM ポリシーをアタッチするとどんどん管理が煩雑になりますよね。
IAM グループを使用すると、複数のIAM ユーザーを一元的に管理することが可能になります。
IAM ユーザーに行ったようにIAM グループに対してポリシーをアタッチすることでグループに属するIAM ユーザーに対して権限を付与できます。

IAM ロール

IAM ユーザーやグループは比較的理解しやすいものだと思っています。
IAM ポリシーに関しては細部まで理解するのは難しいですが何をするものかや、基本的な設定については理解できると思っています。

IAM ロールもIAM ユーザーと同じで認証の役割を担っており、権限の付与のためにIAM ポリシーを使用します。
これだけだと、IAM ユーザーと変わりがないようにみえます。

IAM ユーザーとの決定的な違いは2点あります。

  • アクセス権を別アカウントのAWSユーザーやAWSサービス、アプリケーションなどに委任する
  • 長期認証情報(パスワードやアクセスキー)を持たない

IAM ユーザーと権限は1対1の関係(ポリシーでのプリンシパルの話を思い出してください)になっていますし、パスワードかアクセスキーを必ず持っていますよね。
なのでIAM ロールを理解する上でIAM ロールは権限を委任するものであることと、長期認証情報を持たないと言うことを念頭においてください。理解が捗ります。

IAM ロールの仕組み

IAM ロールの基本的な構造は図にするとこんな感じです。

例えば、EC2インスタンスに対してIAM ロールをアタッチして、S3へアクセスできるようにするとこんな感じです。

ここからちょっと何言ってるか分からないことが増えてしまいます。ですが少しだけお付き合いください。
まずはIAM ロールの特徴を思い出しましょう。
IAM ロールの特徴は権限を委任するもの長期認証情報を持たないという2点でしたよね。
裏を返せばどのように権限を委任するのかと、認証情報をどうするのかの2点が解明できればIAM ロールの仕組みがわかりますね。

権限の委任方法

どのように権限を委任するか、すなわち第三者に対して自分のAWSアカウントのリソースに対しての権限をどのように与えているかを解明していきます。
委任の方法は単純で2つのポリシーをIAM ロールに対してアタッチします。
IAM ユーザーやグループの時と同じようにどのリソースに対してどんな権限を付与するかを定義するポリシーと、信頼関係というポリシーをアタッチします。
前者については既に説明済みなので省略しますが、後者については初めて出た言葉ですね。
この信頼関係こそが、IAM ロールで委任を可能にするためのキーなのです。
実際に信頼関係がどのようなものかみてみましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "ec2.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}

信頼関係というから今までとは全くの別物かと思いきやそんなことはありません。ポリシー作成時のポリシー言語と全くもって同じです。
IAM ユーザーのために作ったポリシーとの違いは2点だけです。

  • Principalが指定されている
  • Actionsts:AssumeRoleになっている

プリンシパルに対してどの委任先(今回の場合はEC2)がこのIAM ロールをアタッチできるかを指定します。
これを指定しないと誰にでも委任できる、脆弱な仕組みになってしまいます。
要は何に対して権限を委任できるかを指定するから信頼関係と呼ばれているんだと思います。
2点目のsts:AssumeRoleについては次の項で説明するので一旦省略させてください。

IAM ロールは同アカウントのAWSサービスのみならず、別アカウントのAWSユーザーなどにもアタッチできます。
その際にはこんな感じの信頼関係を結びます。
AWSアカウント123456789012のhogehogeというIAM ユーザと信頼関係を結んでいます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::123456789012:user/hogehoge" },
      "Action": "sts:AssumeRole"
    }
  ]
}

また、委任先でもMFAを有効にしたい場合はこんな感じになります。
条件部分にMFAの項目を追加しただけです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::123456789012:user/hogehoge" },
      "Action": "sts:AssumeRole",
      "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" }}
    }
  ]
}

IAM ロールは信頼関係を結ぶことで権限の委任を可能にしていることがわかったところで、認証情報の生成方法とsts:AssumeRoleについて確認していきましょう。

認証情報について

IAM ロールではどのように認証情報を生成しているのでしょうか。
その鍵を握るのはsts:AssumeRoleです。
ポリシーのAction部分は基本的にサービス名:アクションなのですが覚えていますか。
言い換えると、STSというサービスとAssumeRoleというアクションこそが鍵なのです。
なのでSTSを確認していきましょう。

STS(Security Token Service)は一時的なセキュリティ認証情報を生成するためのAWSサービスです。
一時的なセキュリティ認証情報は期限付きのアクセスキー、シークレットアクセスキー、セッショントークンで構成されています。
IAM ユーザーのアクセスキーが有効期限付きに変わり、セッショントークンを追加した物です。
なんとなくIAM ロールはSTSを使って認証情報を取得していることがわかりましたね。

AssumeRoleはSTSに対してIAM ロールのARNを渡す代わりに一時的なセキュリティ認証情報を求めるアクションです。
似たようなアクションとして、SAMLを使用した場合に用いるAssumeRoleWithSAMLなどもあります。


ここまでの話をまとめるとこうなります。

  1. IAM ロールはAWSサービスや他AWSアカウントのIAM ユーザーと信頼関係を結んでいる
  2. sts:AssumeRoleで一時的な認証情報を取得している
  3. 一時的な認証情報を元にAWSリソースに対してアクションしており、ポリシーでアタッチした分の権限のみ使える

IAM ロールご理解いただけたでしょうか。
またIAM ロールのユースケースはこんな感じになります。

  • EC2やLambdaなどのAWSサービスのサービスに対してAWSリソースへの権限を付与する
  • 別のAWSアカウントのIAM ユーザーのためにIAM ロールを作ることで認証情報をたくさん持たないようにする(クロスアカウントアクセス)
  • SAML 2.0やOpenID Connectと互換性があるIDプロバイダによって認証された外部ユーザに対してAWSへのアクセス権限を付与する

ID プロバイダーとフェデレーション

すでに社内ディレクトリなどでユーザを管理している場合もあります。
その場合は社内ディレクトリでのユーザ管理に加えて、IAM ユーザーの管理をする必要はありません。
IAMは既存のディレクトリサービスのユーザに対してAWSへのアクセス権限を付与することもできます。

そのために使用するのが、IAM IDプロバイダーです。
IAM IDプロバイダーはOpenID Connectか、SAML 2.0と互換性があるIdPとの間で信頼関係を結び、一時的な認証情報を渡します。
なんとなく聞いたことのある単語が出てきましたね。
そうです、基本的な仕組みはIAM Roleで学んだことと同じです。
IAM RoleがAWS内での信頼関係を結んでいたのに対して、IAM ID プロバイダーは外部のIdPと信頼関係を結んでいるだけです。
そして一時的な認証情報の取得のために、IAM RoleとAWS STSを使用しています。

IAMのベストプラクティス

IAMのベストプラクティスをまとめてみました。
もし設定していない場合や、あまりよくない設定をしている場合はぜひ設定を見直してみてください。

  • ルートユーザ
    • ルートユーザは基本的に使用しない
    • ルートユーザに対してアクセスキーを発行しない
    • ルートユーザにはMFA(多要素認証)を有効にする
  • IAM ユーザー
    • ユーザ単位でIAM ユーザーを作成する
    • 強い権限(AdministratorAccess、PowerUserAccessなど)を持つIAM ユーザーにはMFA(多要素認証)を有効にする
    • アカウントを使いまわさない
    • 強力なパスワードポリシーを設定する
    • 既存のディレクトリサービスがある場合は、IAM ID プロバイダーを検討する
  • IAM ポリシー
    • 最小限のポリシーのみ付与する
    • 管理ポリシーの使用をまず検討する
    • インラインポリシーを使わない
  • IAM ロール
    • AWSリソースから別のAWSリソースに対してアクセスする場合はIAM ロールを使用する(IAM ユーザーを作らない)
    • アカウント間での認証情報共有をしないでクロスアカウントアクセスを設定する

やってみよう

実際に試してみないことには理解は深まりません。
IAMを触っていきましょう。
また、これらを試した後は必ず、リソースを削除しましょう。

IAM ユーザーの作成

IAM ユーザーを作っていきます。
マネジメントコンソールを開いて一緒に進めていきましょう。
開きましたら次はIAMに移動して左上のIAM ユーザーをクリックします。
そして、「ユーザーを追加」をクリックします。

次にIAM ユーザーの情報を入力していきます。
ユーザ名はなんでも大丈夫です(誤字があっても作られるので気をつけましょう)。
今回はマネジメントコンソールへのアクセス用IAM ユーザーを作成するので、アクセス種別のうち、「AWSマネジメントコンソールへのアクセス」を選択します。
また、パスワード生成もちょっと手間だったので自動生成するようにしてます。

アクセス許可の設定で通常はここでポリシーの設定をするのですが、あえてスキップします。

タグはご自由にどうぞ。
今回はなんとなくつけてないです。普段はNameタグを必ずつけてます。

そしたらユーザの作成に進んでください。

追加されたIAM ユーザーのパスワードとマネジメントコンソールへのログインurl(画面中央上部のもの)をメモしておきます。

ここまでできたら、一旦サインアウトするか、シークレットタブを開いてください。
先ほど作ったIAM ユーザーでアクセスしてみましょう。

無事ログインできたでしょうか。
もしできたなら、EC2に進んでみてください。
スクリーンショットのように何も権限を持っていないのでリソースに対して何もできませんね。

IAM ポリシーの作成

IAM ユーザーを作っても何もできませんでしたね。
権限が必要なのですね。権限の付与のためにもIAM ポリシーを作ってアタッチしましょう。

マネジメントコンソールを開いて一緒に進めていきましょう。
開きましたら次はIAMに移動して左上のIAM ポリシーをクリックします。
次に「ポリシーの作成」をクリックします。

今回はEC2へ対するアクセスをできるようなポリシーを作成します。
ポリシーの中身はこんな感じなので、これをJSONを押して、出てきたエディタに貼り付けましょう。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "ec2:*",
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "elasticloadbalancing:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "cloudwatch:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "autoscaling:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:AWSServiceName": [
                        "autoscaling.amazonaws.com",
                        "ec2scheduled.amazonaws.com",
                        "elasticloadbalancing.amazonaws.com",
                        "spot.amazonaws.com",
                        "spotfleet.amazonaws.com",
                        "transitgateway.amazonaws.com"
                    ]
                }
            }
        }
    ]
}

そしたら作成するポリシーに好きな名前をつけましょう。

ポリシーが無事できたところで、ユーザー一覧に移動しましょう。
移動したら先ほど作成したユーザーをクリックします。

アクセス権限の追加を押します。

ポリシーのフィルターで「ユーザーによる管理」を押します。

先ほど作ったポリシーを選択します。

ポリシーをアタッチします。

ここまでできたら、一旦サインアウトするか、シークレットタブを開いてください。
先ほど作ったIAM ユーザーでアクセスしてみましょう。
今度はEC2に対してのアクセス権限があるので色々な情報がみれますね。

ちょっと簡単だったでしょうか。
IAMは他にも様々なユースケースや使用方法があるのでぜひ調べてみてください。

さいごに

少しでもIAMに寄り添えるようになりましたか。なっていれば幸いです。

明日(7/10)の岩城の「AWS CloudFormation」編です。お楽しみに!!