はじめに

アプリケーション開発部の田村です。自社で運営するサービス開発を担当しています。 私が担当するサービス開発では実行環境にAWSを利用しています。
今回、 許可したIPアドレスからのみAWSマネジメントコンソールを操作できる設定についてお話します。

AWSの作業や調査を行う上で欠かせないAWSマネジメントコンソールですが、もし不正ログインをされた場合その被害は甚大です。

AWSマネジメントコンソールはどこからでもアクセス出来るため、 セキュリティ強化が求められる今、許可IPアドレスからのみ操作を許可するといったセキュリティ対策は実施おきたいところです。

ただ、AWSマネジメントコンソールには「許可IPアドレス以外からのログインを拒否する」といった設定が現状出来ません。

しかし不正ログインされても「許可IPアドレス以外からのログインされた場合、有効な操作はさせない」という設定は可能なのでそれについてお話します。

実現手段

下記の仕組みで実現します。

・操作を許可する(例えばAmazon S3権限など)IAMロールを定義する
・IAMロールに運用上必要な操作権限(Amazon S3の読み取りなど)をアタッチする
・そのIAMロールを引き受けるIAMユーザを作成する
・そのIAMユーザは許可IPアドレスからアクセスした時だけ、そのIAMロールにスイッチできる

上記の設定により、ログインした直後は運用上必要な権限を持ちませんが、スイッチロールすると権限を持つことができます。 ただしそのスイッチロールは許可IPアドレスからログインした時のみ行うことができます。

IAMポリシーのConditionaws:SourceIpで制御する方法もありますが、AWSの仕組み上ハマるポイントが多いので避けたほうが無難です。
その場合のハマるポイントとしては以下の通りです。

  • VPCエンドポイント内からのAPIコール
    • 例えば、VPC内にAWS Workspacesを立ち上げ、そのAWS WorkspacesからVPCエンドポイント経由でAmazon S3にアクセスした場合
  • AWSサービスがユーザに代わってAPIコール(ユーザの認証情報は利用)
    • 例えば、EC2で暗号化EBSを作成する場合(KMSの実行でエラー)
    • AWS CloudFormationなど

いずれもアクセス元のIPがユーザのアクセス元IPとは異なってしまうため拒否されてしまいます。
※簡易イメージ図
※★がAWSの認識するアクセス元IP。

これらに対処するにはIAMポリシーのConditionaws:ViaAWSServiceaws:SourceVpceなどを用いる必要があります。

https://d1.awsstatic.com/webinars/jp/pdf/services/20150225_AWS-BlackBelt-ManagementConsole.pdf
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-viaawsservice

それに比べスイッチロールのほうが仕組みはシンプルでわかりやすいです。
確かにログイン後に毎回スイッチロールする必要はありますが複雑な条件に悩まされることはありません。
それでは設定方法を解説していきます。

許可IPアドレスからのみ操作を許可するIAMポリシー

下記の想定で説明を進めます。

    • システムの運用を担当するIAMユーザに許可IPアドレスからのみ操作を可能とする
    • Amazon S3のバケットの閲覧のみ可能とする

運用担当者のIAMユーザを作成

まずIAMユーザを作成します。 AWS IAMの画面の「ユーザー」から「ユーザーを追加」で作成します。
ユーザー名は「Operator」としました。

後続の画面はデフォルト値のまま進めて最後に「ユーザーの作成」を押下して完了です。

操作を許可するIAMポリシーを作成

「S3のバケットの閲覧」の操作を許可するIAMポリシーを作成します。
AWS IAMのIAMポリシーの画面を開いて「ポリシーを作成」で新規に作成します。
ここではAmazon S3の閲覧権限を付与しますが、みなさんの運用に応じて必要な権限を許可してください。

「ReadOnlyForOperator」という名前にしました。「ポリシーの作成」を押下します。

IAMロールを作成

IAMロールを作成し、先程作成したIAMポリシーをアタッチします。
AWS IAMのIAMロールの画面を開き「ロールを作成」を押下します。
「別のAWSアカウント」を選択し、アカウントID(12桁の数字)を入力します。アカウントIDはマイアカウントなどから探すことが出来ます。
今回は設定しませんが「MFAが必要」にチェックを入れると、MFA認証が有効なIAMユーザしかこのIAMロールを引き受けることができなくなるためよりセキュリティを強固に出来ます。

IAMポリシーは先程作成したものをアタッチします。

最後に名前を入力し「ロールの作成」を押下して作成します。
名前は「Operator_IPRestriction」としました。

IAMロールの信頼関係の編集

最初に作成したIAMユーザ「Operator」がこのIAMロールを引き受けることが出来るように信頼関係を編集します。
また引き受けることが出来る条件として許可IPアドレスからログインした場合を制限として加えます。

先にIAMユーザ「Operator」のarnをIAMユーザの画面で確認して控えておきます。

次に作成したIAMロール「Operator_IPRestriction」を開き、「信頼関係の編集」を押下します。

編集画面で下記のようにします。
Princhipalのところには控えておいたIAMユーザのarnを設定します。
下記のように、まずsts:AssumeRoleを許可する設定をいれておき、許可IPアドレス以外からのsts:AssumeRoleは明示的に拒否する設定を入れています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:user/Operator"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:user/Operator"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx/32"
        }
      }
    }
  ]
}

ちなみに下記のように許可IPアドレスからアクセス時のみ許可する条件でも実現することは可能です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:user/Operator"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx/32"
        }
      }
    }
  ]
}

しかしこの設定には少し弱い部分があります。
IAMロールには複数個のIAMポリシーをアタッチ出来るわけですが、例えばこのIAMロールに誤って下記のようなIAMポリシーを追加したとします。IPアドレスによる制約条件がありません。

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

これではどのIPからでもスイッチロールが出来てしまいます。

今回実現したい運用において最重要ポイントは「許可されたIPアドレスからのみ操作できること」です。
この要件が上記のようなちょっとしたミスで脅かされないようにしないといけません。

そこで「明示的な拒否」です。
これはIAMポリシーに「この操作は禁止」ということを明確に定義することです。
IAMポリシーにおいて「明示的な拒否」(Deny)は「明示的な許可(Allow)」よりも優先されます。

最初の許可IPアドレス以外からのsts:AssumeRoleを明示的に拒否する設定は、上記の誤った許可設定が追加されても負けません。
よって要件を満たす設定は維持されます。

入力できたら「信頼ポリシーの更新」を押下します。

設定はこれで完了です。

ちなみに今回はクロスアカウントでのロールの引き渡しではないため、IAMユーザのIAMポリシーでsts:AssumeRoleを許可する必要がありません。

https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
「If the user is in the same account as the role….」の付近。

確認

では実際にログイン–>スイッチロール–>S3バケットの閲覧までを確認してみましょう。

まず許可IPアドレスのアクセス元から作成したIAMユーザで普通にAWSマネジメントコンソールにログインします。
この時点ではAmazon S3を見る権限はありません。 「ロールの切り替え」を行います。

下記のように入力します。「アカウント」はアカウントID、ロールは作成したIAMロールです。

スイッチロールをするとアカウント表示の箇所にIAMロール名が見えます。
Amazon S3のバケットリストが正常に見えています。

許可IPアドレス以外からログインした場合ですが、想定どおりスイッチロールが出来ません。

まとめ

スイッチロールを上手に利用することで実現したい運用が出来るようになりました。
これに加えてAWS Management Consoleのログインをメール通知するのログイン通知を設定しておくことでさらにセキュリティレベルが向上します。


本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。