IAMポリシーの条件キーでMFA認証済みユーザーのみに操作を許可する方法

目次

概要

IAMポリシーでは、条件(Condition)を使ってアクセスを細かく制御できます。その中でもMFA(多要素認証)に関連する条件キーは、セキュリティ要件の高い操作を保護するために頻繁に使用されます。

本記事では、S3バケットの一覧表示をMFA認証済みのユーザーのみに制限するポリシーの設計を通じて、MFA関連の条件キーの使い分けを解説します。

 この記事のメリット

  • aws:MultiFactorAuthPresent と aws:MultiFactorAuthAge の違いを正確に理解できる
  • MFA認証を強制するIAMポリシーの書き方を習得できる
  • AllowポリシーとDenyポリシーでの Bool / BoolIfExists 演算子の使い分けを理解できる
  • SCS試験の「IAMポリシー条件キー」に関する問いに正確に答えられるようになる

 技術解説

 IAMポリシーの条件キーとは

IAMポリシーの Condition 要素では、リクエストのコンテキスト情報を条件として評価できます。条件キーはAWSがリクエストごとに自動で付与するメタデータで、aws: プレフィックスが付くグローバル条件キーはすべてのAWSサービスで共通して使用できます。

以下は、条件キーを含むIAMポリシードキュメントの全体像です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ExampleWithCondition",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*",
            "Condition": {
                "演算子": {
                    "条件キー": "値"
                }
            }
        }
    ]
}

Condition 要素は Statement の中に記述し、「演算子」と「条件キー: 値」の組み合わせで条件を指定します。この条件が一致した場合にのみ、Effect(Allow または Deny)が適用されます。

 MFA関連の条件キー

MFAに関連するグローバル条件キーは主に2つあります。

条件キー説明
aws:MultiFactorAuthPresentBooleanリクエスト時にMFA認証が行われたかどうか
aws:MultiFactorAuthAgeNumericMFA認証からの経過秒数

 aws:MultiFactorAuthPresent

MFA認証済みかどうかを true / false で判定します。「MFA認証を行ったユーザーのみ操作を許可する」というシンプルな要件に適しています。

"Condition": {
    "Bool": {
        "aws:MultiFactorAuthPresent": "true"
    }
}

 aws:MultiFactorAuthAge

MFA認証が行われてからの経過秒数を数値で評価します。「MFA認証後5分(300秒)以内のみ許可する」のように、MFA認証からの有効時間を制限する場合に使用します。

"Condition": {
    "NumericLessThan": {
        "aws:MultiFactorAuthAge": "300"
    }
}

この条件キーは「MFA認証済みかどうか」ではなく「MFA認証からどれだけ時間が経過したか」を判定するものです。単にMFA認証の有無を確認したい場合には適していません。

 Allowポリシーで使う場合の注意点

本記事の実践で使用する Allow + Bool の組み合わせでは、CLIから長期アクセスキーで直接リクエストした場合に aws:MultiFactorAuthPresent キー自体がリクエストコンテキストに含まれません。この場合、条件が一致しないため Allow が発動せず、結果としてアクセスは拒否されます。つまり Allow ポリシーでは Bool 演算子で安全に動作します。

なお、マネジメントコンソールやサービス間の連鎖呼び出しなど、AWSがIAMユーザーの代わりに裏で一時認証情報を生成するケースでは、キーはリクエストコンテキストに存在し false に設定されます。

長期アクセスキーと一時認証情報

「長期アクセスキー」とは、IAMユーザーに発行されるアクセスキーID(AKIA で始まる)とシークレットアクセスキーのペアのことです。有効期限がなく、明示的に削除または無効化するまで永続的に使用できます。一方、aws sts get-session-token や aws sts assume-role で取得する一時認証情報(アクセスキーIDが ASIA で始まる)には有効期限があり、セッショントークンが付属します。

 Denyポリシーで使う場合の注意点(BoolIfExists)

一方、MFA未認証時にアクセスを明示的に拒否する Deny ポリシーを書く場合は注意が必要です。

以下は 危険な書き方 の例です。

"Effect": "Deny",
"Condition": {
    "Bool": {
        "aws:MultiFactorAuthPresent": "false"
    }
}

この書き方では、CLIから長期アクセスキーで直接リクエストした場合にキー自体が存在しないため、条件が「一致しない」と評価されます。その結果、Deny が発動せずアクセスが許可されてしまいます。

安全に Deny パターンを使うには、BoolIfExists 演算子を使用します。IfExists 修飾子はキーが存在しない場合に条件を true(一致)として評価するため、長期アクセスキーからのリクエストも確実に拒否できます。

以下は 安全な書き方 の例です。

"Effect": "Deny",
"Condition": {
    "BoolIfExists": {
        "aws:MultiFactorAuthPresent": "false"
    }
}
パターン演算子長期アクセスキー(キー不在)時の挙動
Allow + Bool: "true"Bool条件不一致 → Allow不発動 → 安全
Deny + Bool: "false"Bool条件不一致 → Deny不発動 → 危険
Deny + BoolIfExists: "false"BoolIfExists条件一致 → Deny発動 → 安全

 条件キーの比較

条件キー用途MFA判定に使えるか
aws:MultiFactorAuthPresentMFA認証済みかどうかの判定はい
aws:MultiFactorAuthAgeMFA認証後の経過時間の制限間接的(時間制限)

 MFA強制ポリシーと初期設定問題

本記事のように特定の操作に条件を付与するケースでは問題になりませんが、「MFA未認証ならすべての操作を拒否する」グローバルな Deny ポリシーを設計する場合、MFAデバイスの登録やセッショントークンの取得といったMFAセットアップに必要な操作自体も拒否されてしまい、ユーザーがMFA認証を完了できなくなるブートストラップ問題が発生します。

この場合、iam:CreateVirtualMFADevice や iam:EnableMFADevicests:GetSessionToken などのMFAセットアップに必要なアクションを NotAction で除外する設計が必要です。

実践

ここでは、検証用のIAMユーザーを作成し、MFA認証済みのユーザーのみにS3バケットの一覧表示を許可するIAMポリシーをアタッチして、MFA認証の有無による挙動の違いをコンソールとCLIの両方で確認します。

 前提条件

  • リージョン: ap-northeast-1(東京)
  • 作業用IAMユーザーでIAMの操作権限があること
リソース種別リソース名用途
IAMユーザーmfa-test-user検証用ユーザー
IAMポリシーMFARequiredS3ListPolicyMFA認証済みユーザーのみにS3一覧表示を許可

 検証用IAMユーザーの作成

  • AWSマネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。
  • 上部の検索バーに IAM と入力し、表示された「IAM」を選択します。
  • 左側ナビゲーションの「ユーザー」を選択します。
  • 右上の「ユーザーの作成」をクリックします。
  • ユーザー名に mfa-test-user と入力します。
  • 「AWS マネジメントコンソールへのユーザーアクセスを提供する」にチェックを入れます。
  • 「IAM ユーザーを作成します」を選択します。
  • 「カスタムパスワード」を選択し、任意のパスワードを入力します。
  • 「ユーザーは次回のサインイン時に新しいパスワードを作成する必要があります」のチェックを外します。
  • 「次へ」をクリックします。
  • 許可の設定はそのまま「次へ」をクリックします。
  • 「ユーザーの作成」をクリックします。
  • サインインURLとパスワードを控えておきます。

 IAMポリシーの作成

  • 左側ナビゲーションの「ポリシー」を選択します。
  • 右上の「ポリシーの作成」をクリックします。
  • 「JSON」タブを選択し、以下のポリシーを入力します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowMFASetup",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:GetUser"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowS3ListOnlyWithMFA",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        }
    ]
}
  • 「次へ」をクリックします。
  • ポリシー名に MFARequiredS3ListPolicy と入力します。
  • 「ポリシーの作成」をクリックします。

 IAMユーザーへのポリシーのアタッチ

  • 左側ナビゲーションの「ユーザー」を選択します。
  • mfa-test-user を選択します。
  • 「許可」タブの「許可を追加」→「ポリシーを直接アタッチする」を選択します。
  • 検索バーに MFARequiredS3ListPolicy と入力し、表示されたポリシーにチェックを入れます。
  • 「次へ」→「許可を追加」をクリックします。

 MFA未設定状態でのコンソール動作確認

  • ブラウザのシークレットウィンドウを開きます。
  • 検証用IAMユーザーの作成時に控えたサインインURLにアクセスし、mfa-test-user のユーザー名とパスワードでログインします。
  • 上部の検索バーに S3 と入力し、表示された「S3」を選択します。
  • バケット一覧画面で「バケットを表示するアクセス許可がありません。」というエラーメッセージが表示されることを確認します。

MFA認証が行われておらず aws:MultiFactorAuthPresent の条件を満たせていないので、ListAllMyBucketsが許可されていない状態です。

 MFAデバイスの設定

  • シークレットウィンドウで mfa-test-user にログインした状態のまま、右上のユーザー名をクリックし「セキュリティ認証情報」を選択します。
  • 「多要素認証(MFA)」セクションの「MFA デバイスの割り当て」をクリックします。
  • デバイス名に任意の名前を入力します。
  • 「認証アプリケーション」を選択し、「次へ」をクリックします。
  • 「QR コードを表示」をクリックし、認証アプリ(Google Authenticator 等)でスキャンします。
  • 認証アプリに表示される連続する2つのMFAコードを入力し、「MFA を追加」をクリックします。

 MFA認証済み状態でのコンソール動作確認

  • シークレットウィンドウで一度サインアウトします。
  • 再度 mfa-test-user でサインインします。パスワード入力後、MFAコードの入力画面が表示されます。
  • 認証アプリに表示されるMFAコードを入力してサインインを完了します。
  • 上部の検索バーに S3 と入力し、表示された「S3」を選択します。
  • バケット一覧が表示されることを確認します。

MFA認証を経てサインインしたため、aws:MultiFactorAuthPresent が true となり、S3バケットの一覧表示が許可されます。

 CLIでのMFA未認証状態の動作確認

CLIでの挙動も確認します。作業用ユーザでサインインしてmfa-test-user のアクセスキーを作成し、長期アクセスキーで直接リクエストした場合の挙動を確認します。

  • 作業用IAMユーザのコンソールに戻り、IAMの mfa-test-user のユーザー詳細画面を開きます。
  • 「セキュリティ認証情報」タブの「アクセスキー」セクションで「アクセスキーを作成」をクリックします。
  • ユースケースとして「コマンドラインインターフェイス(CLI)」を選択し、確認のチェックを入れて「次へ」をクリックします。
  • 「アクセスキーを作成」をクリックし、アクセスキーIDとシークレットアクセスキーを控えます。

CLIプロファイルを設定します。

aws configure --profile mfa-test-user

アクセスキーIDとシークレットアクセスキーを入力し、リージョンに ap-northeast-1 を指定します。

MFA認証なしでS3バケット一覧を取得してみます。

aws s3 ls --profile mfa-test-user

MFA認証を行っていないため、アクセスが拒否されます。

An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::<ACCOUNT_ID>:user/mfa-test-user is not authorized to perform: s3:ListAllMyBuckets because no identity-based policy allows the s3:ListAllMyBuckets action

 CLIでのMFA認証済み状態の動作確認

MFA認証済みの一時認証情報を取得する方法には、従来の aws sts get-session-token を使う方法と、AWS CLI v2.32.0 以降で利用可能な aws login を使う方法がありますが現在推奨されている後者の方法を実践します。

 aws login を使う方法(推奨)

AWS CLI v2.32.0 以降では、aws login コマンドでブラウザベースのMFA認証が可能です。長期アクセスキーの発行や環境変数の手動設定が不要で、認証トークンは有効期限前に自動リフレッシュされます。

aws login を使用するには、mfa-test-user に SignInLocalDevelopmentAccess マネージドポリシーをアタッチするか、以下のアクションを許可する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "signin:AuthorizeOAuth2Access",
                "signin:CreateOAuth2Token"
            ],
            "Resource": "*"
        }
    ]
}

権限を付与したら、以下のコマンドを実行します。

aws login --profile mfa-test-user-cli

コマンドを実行するとブラウザが自動的に開き、マネジメントコンソールと同じ画面でMFA認証を行います。

認証が完了すると、CLIが自動的にMFA認証済みの一時認証情報を使用できる状態になります。

既存のプロファイルと競合している場合

指定したプロファイル名が存在する場合は以下のエラーになります。既存のものを削除するか、登録するプロファイル名を変更して回避しましょう。

Profile ‘default’ is already configured with Credential Process credentials.

You may run ‘aws login –profile new-profile-name’ to create a new profile with the specified name. Otherwise you must first manually remove the existing credentials from ‘default’.

S3バケット一覧を取得します。

aws s3 ls --profile mfa-test-user-cli

MFA認証済みのため、バケット一覧が表示されます。

 まとめ

MFA認証済みユーザーのみにアクセスを制限する場合の条件キーの選択基準は以下の通りです。

要件使用する条件キー
MFA認証済みかどうかを判定したいaws:MultiFactorAuthPresent
MFA認証後の有効時間を制限したいaws:MultiFactorAuthAge

また、Deny ポリシーで aws:MultiFactorAuthPresent を使用する場合は、長期アクセスキーからのリクエストでキーが存在しないケースに対応するため、Bool ではなく BoolIfExists 演算子を使用する必要があります。

SCS試験では、条件キーの名前が似ているものが選択肢に並ぶことがあります。各条件キーが「何を評価するのか」を正確に把握し、要件に合った条件キーを選択できるようにしておきましょう。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社Luxy(https://luxy-inc.com)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した会社を引き継ぎ、代表に就任。

目次