😊

AWSアカウントを作ったときこれだけはやっとけって言うIAMの設定

2021/11/14に公開

はじめに

個人でも仕事でもAWSを使っている時に気になるのはセキュリティですよね。
万が一アクセスキーなどが漏れてしまい、それが何でも出来ちゃうユーザーだったら
もう大変なことになります。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html
ただAWSのIAMはAWSの中でも一番難しいサービスなのでは?と思うくらい複雑です。
その中でも簡単ですぐにも実践出来るTipsを4つ紹介します。

目次

  1. MFA認証してない時の権限を最小にする
  2. IAMユーザーのMFAデバイスを有効化する
  3. ユーザーに権限を委任するロールを作成する
  4. CLIを使う時も、MFA認証してロールを切り替える

1. MFA認証してない時の権限を最小にする

まず、下記のポリシーを作業用のユーザーに紐付けます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:ListVirtualMFADevices"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreateVirtualMFADevice",
        "iam:DeleteVirtualMFADevice"
      ],
      "Resource": "arn:aws:iam::*:mfa/${aws:username}"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:DeactivateMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ResyncMFADevice"
      ],
      "Resource": "arn:aws:iam::*:user/${aws:username}"
    },
    {
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ListVirtualMFADevices",
        "iam:ResyncMFADevice",
        "iam:ChangePassword",
        "iam:GetAccountPasswordPolicy"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}

ポイントとなるのは

{
  "Effect": "Deny",
  "NotAction": [
    "iam:CreateVirtualMFADevice",
    "iam:EnableMFADevice",
    "iam:GetUser",
    "iam:ListMFADevices",
    "iam:ListVirtualMFADevices",
    "iam:ResyncMFADevice",
    "iam:ChangePassword",
    "iam:GetAccountPasswordPolicy"
  ],
  "Resource": "*",
  "Condition": {
    "BoolIfExists": {
      "aws:MultiFactorAuthPresent": "false"
    }
  }
}

の部分です。

IAMポリシーはConditionブロックでポリシーを実行するタイミングを定義できるのですが、
aws:MultiFactorAuthPresentをfalseにすることで、「MFAで認証していない時」という
条件を表現ことが出来ます。

つまり、上記のポリシーはMFAで認証していない時、NotAction
指定したアクション以外の全てのアクションを拒否することを意味しています。

2. IAMユーザーのMFAデバイスを有効化する

次にMFAを有効にします。まず、「マイセキュリティ資格情報」を選択します。

「AWS IAM認証情報タブ」から「MFAデバイスの割り当て」を選択します。

表示されたモーダルから「仮想MFAデバイス」にチェックを入れて、続行をクリックします。

次に多要素認証アプリでQRコードを読み込み、コードを2回連続で入力します。

他要素認証アプリは色々あると思いますが、私は「Okta Verify」を使っています。
理由としてはApple Watchにも対応しているのでコードを入力するのに一々スマホを
開かなくても良いのが気に入ってます。

コードを入力して「MFAの割り当て」をクリックすればMFAデバイスが有効になります。
一度サインアウトしてMFAが有効になっているか試してみましょう。

3. ユーザーに権限を委任するロールを作成する

現在の権限では何も出来ませんが、IAMロールを作成することで、通常はリソースへアクセスする
権限のないユーザーに一時的にアクセスする権限を委任できます。

IAMロールのコンソールから「IAMロールを作成」を選択します。

「別のAWSアカウント」を選択してアカウントIDを入力し,
「MFAが必要」にチェックを入れます。

付与する権限ですが、とりあえずここでは AdministratorAccess を選び、
ロール名やタグを入力してロールの作成は完了となります。

次にロールの信頼関係を編集します。

「信頼関係」のタブから「信頼関係の編集」を選択してポリシードキュメントを
次の様に編集します。

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

PrincipalにIAMユーザーのARN指定して、このロールにAssumeRoleすることを許可します。

次に、このロールにAssumeRoleすることを許可するポリシーを作成して、
IAMユーザーに紐付けます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Resource": "arn:aws:iam::762742784206:role/AdminRole"
    }
  ]
}

ロールの切り替えはめっちゃ簡単でIAMロールのコンソールに表示されているURLに
アクセスすれば実行出来ます。これでMFA認証している時、一時的にIAMユーザーに
権限を付与することが出来る様になりました。

ただ、このユーザーにはロールを切り替える前はほとんど権限が付与されておらず、
AWS CLIを使いたい!となった時に何も出来ません。とはいえせっかくコンソールでMFA認証を
有効にしたのだからCLIでもちゃんとMFA認証してロールを切り替えて作業したいです。

4. CLIを使う時も、MFA認証してロールを切り替える

まず、GetSessionToken APIで一時的な認証情報を取得します。ちなみにこのAPIを利用するのに
新しくポリシーを追加する必要はありません。IAMユーザーのアクセスキーを発行してcredentialsを修正してから、次のコマンドを実行してみます。

$ aws sts get-session-token --serial-number arn:aws:iam::732458568412:mfa/machamp --token-code 123456 --profile machamp
{
  "Credentials": {
    "AccessKeyId": "ASIA3DFYDIDHPGNJF3NB",
    "SecretAccessKey": "Brpa3W4o6scL5JMiuyWQREUHoUznAE3/FVgviA1z",
    "SessionToken": "FwoGZXIvYXdzECgaDGslzvGbgdX65JWDLiKGAdEEypeN4EvTA16c0CUfXn8dZIg5Z1ZTjnkKL/MAJlhplAli6DkQdclnNMC4Cx9373Gey0I6N5q5Oucu1/1Z4wW+OKq",
    "Expiration": "2021-11-09T02:57:20+00:00"
  }
}

するとこの様に期限付きのアクセスキーを取得することができます。

[sample-mfa]
aws_access_key_id = ASIA3RAIE64EFCDXOPFU
aws_secret_access_key = dsVW7VPAgjS/U7VW2TFRCOdCxY5POcIE3SUx6tI3
aws_session_token = FwoGZXIvYXdzECgaDGslzvGbgdX65JWDLiKGAdEEypeN4EvTA16c0CUfXn8dZIg5Z1ZTjnkKL/MAJlhplAli6DkQdclnNMC4Cx9373Gey0I6N5q5Oucu1/1Z4wW+OKq

取得したアクセスキーをcredentialsに貼り付ければ、
profileに sample-mfa を指定してCLIを使うことが出来ます。

ただ、毎回CLIを使うたびにキーを取得してコピペするのは面倒です。
そこでこの辺を自動化できるシェルを書いてみました。参考にしてください。

#!/bin/sh

MFA_TOKEN=$1

JSON=`aws sts get-session-token --serial-number arn:aws:iam::792438568712:mfa/machamp --token-code $MFA_TOKEN --profile machamp`

if [ -z "${JSON}" ]; then
  echo "[Error] Invalid Argument."; exit 1;
fi

AWS_ACCESS_KEY_ID=`echo $JSON | jq -r -c '.Credentials | .AccessKeyId'`
AWS_SECRET_ACCESS_KEY=`echo $JSON | jq -r -c '.Credentials | .SecretAccessKey'`
AWS_SESSION_TOKEN=`echo $JSON | jq -r -c '.Credentials | .SessionToken'`

aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile sample-mfa
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile sample-mfa
aws configure set aws_session_token $AWS_SESSION_TOKEN --profile sample-mfa

ただ、このアクセスキーを使っても実際CLIで出来ることはほとんどありません。
次は、この一時的なアクセスキーで以前作った AdminRole に切り替えてCLIを実行してみます。

[admin-role]
role_arn = arn:aws:iam::732458568412:role/AdminRole
source_profile=sample-mfa

この様に role_arn には切り替え先のロールARNを、source_profile には
ロールを使用するためのアクセス許可を持つIAMユーザーの認証情報を含むプロファイルを
指定することで、ロールに割り当てられたアクセス許可でCLIを使用出来ます。

これでMFA認証をしてさらにロールを切り替えてCLIを実行できる様になりました🎉

参考資料

ハードウェア MFA デバイスの有効化
IAM ユーザーにアクセス権限を委任するロールの作成
IAM ロールの切り替え (AWS CLI)

GitHubで編集を提案

Discussion