1. はじめに
背景
先日、S3のVPCエンドポイントを経由してEC2インスタンスからS3上のファイルにアクセスする検証を行いました。詳細はこちらの記事をご参照ください。
疑問点
この検証を通じて、以下の疑問が生じました:
- EC2インスタンスがS3バケットにアクセスするためには、適切な権限を持つ
IAM Role
が必要です。 -
IAM Role
の認証情報は、AWS Security Token Service (STS)
によって提供されます。 -
STS
を含む多くのAWSサービスは、AWSの独自のグローバルネットワークインフラストラクチャ上に存在し、通常はVPC外にあります。 - AWSサービスへのアクセスには、一般的に以下の2つの方法があります:
- パブリックエンドポイント:インターネット経由でアクセス
- VPCエンドポイント:AWS内部ネットワークを使用してプライベートにアクセス
- 上の図のように今回の検証では、EC2インスタンスはプライベートサブネットに配置されており、インターネットへの直接アクセスはできません。
- S3へのアクセスはS3 VPCエンドポイントを経由して行われていますが、
STS
アクセス用のVPCエンドポイントは別途作成されていません。
これらの状況を踏まえると、以下の疑問が浮かび上がります:
-
プライベートサブネットに配置されたEC2インスタンスが、インターネットアクセスもできないし、
STS
のVPCエンドポイントも持たない状況で、どのようにしてIAM Role
の認証情報を取得できているのでしょうか?
この疑問を解消するために、以下の点について詳しく調査し説明していきます:
- EC2インスタンスプロファイル、
IAM Role
、STS
の関係 - プライベートサブネットのEC2インスタンスから
IAM Role
の認証情報を取得する仕組み
2. 関連コンポーネントの関係
2.1 EC2インスタンスとIAM Role
- EC2インスタンス作成時に、
IAM Role
を関連付けることができます。インスタンス作成時にロールを設定しなくても、インスタンス作成後に関連付けることも可能です。 - この
IAM Role
には、EC2インスタンスが必要とするAWSリソースへのアクセス権限が定義されています。
2.2 EC2インスタンスプロファイルとIAM Role
の関係
- インスタンスプロファイルの役割:主な目的は、EC2インスタンスに安全に
IAM Role
の権限を付与する - IAMロールとの関係:
-
EC2インスタンスに直接
IAM Role
を関連付けることはできません。代わりに、インスタンスプロファイルを通じてIAM Role
をEC2インスタンスに関連付けます - インスタンスプロファイルは、EC2インスタンスと
IAM Role
を結び付けるための箱です - インスタンスプロファイルとIAMロールの関係は一対一です。
-
EC2インスタンスに直接
- 自動作成:
- AWSマネジメントコンソールから
IAM Role
を作成すると、同じ名前のインスタンスプロファイルが自動的に作成されるため、ユーザーがインスタンスプロファイルを意識する必要がありません
- AWSマネジメントコンソールから
- 認証情報の取得:
- EC2インスタンスは、インスタンスプロファイルを通じて、関連付けられた
IAM Role
の一時的な認証情報を取得
- EC2インスタンスは、インスタンスプロファイルを通じて、関連付けられた
要するに、インスタンスプロファイルはEC2インスタンスとIAM Role
の間の橋渡しの役割を果たし、EC2インスタンスがAWSリソースにアクセスするための安全な方法を提供
2.3 インスタンスメタデータサービス(IMDS
)
2.3.1 基本情報
- EC2インスタンス内部で利用可能なHTTPサービス
- 通常、IPアドレス169.254.169.254で提供
- インスタンスに関する情報や
IAM Role
の一時的な認証情報を提供
2.3.2 IMDSの仕組み
IMDS
のIPアドレスは、物理的なサーバーやデバイスを指すものではなく、AWSのインフラストラクチャによって提供される仮想的なエンドポイントです。
-
リンクローカルアドレス
-
169.254.169.254
は、リンクローカルアドレスと呼ばれる特殊なIPアドレスです。 - このアドレスは、ローカルネットワークセグメント内でのみ有効で、インターネットにルーティングされません。
-
-
AWSハイパーバイザーの役割
AWSの仮想化レイヤー(ハイパーバイザー)が、このアドレスへのリクエストをインターセプトし、適切な応答を返します。 -
EC2インスタンス内での動作
EC2インスタンス内からこのアドレスにアクセスすると、リクエストは実際にはインスタンスの外に出ることなく、AWSのインフラストラクチャによって処理されます。
3. EC2インスタンスからIAM Roleの認証情報を取得する仕組み
3.1 認証情報の取得プロセス
EC2インスタンスがIAM Role
の認証情報を取得するプロセスは以下の通りです。
-
リクエストの開始
- EC2インスタンス内のアプリケーションやAWS SDKが
IMDS
にリクエストを送信
- EC2インスタンス内のアプリケーションやAWS SDKが
-
IMDSの処理
-
IMDS
がリクエストを受け取り、STS
サービスに対してAssumeRole
リクエスト
-
-
STS
処理-
STS
サービスは、IAM Role
に基づいて一時的な認証情報を生成し、IMDS
に返す - これらの認証情報は通常、数時間後に期限切れになり、自動的に更新(有効期限はデフォルトでは1時間、最大で12時間まで延長することが可能)
- AWS CLIやAPIを使用する場合、
duration-seconds
パラメータを指定することで、1時間から12時間の間で任意の有効期限を設定可能
-
-
認証情報の提供
-
IMDS
が生成された認証情報をアプリケーションに提供
-
3.2 重要なポイント
-
内部通信:
IMDS
はAWSの内部インフラストラクチャの一部として機能し、STS
サービスとの通信にAWSの内部ネットワークを使用します。この通信はパブリックインターネットを経由せず、AWSの管理下にある特殊なネットワーク経路を使用 -
VPCエンドポイントの不要性:
IMDS
とSTS
の通信はAWS内部で行われるため、VPCエンドポイントを明示的に作成する必要はありません -
透過的な処理: EC2インスタンス上のアプリケーションやSDKからは、この内部通信プロセスは透過的です。アプリケーションは
IMDS
にリクエストを送信するだけで、残りの処理はAWSインフラストラクチャによって自動的に処理されます
private subnetにあるEC2から以下のコマンドでSTSに直接アクセスしようとしても返事が来ない:
$ aws sts get-caller-identity
3.3 セキュリティと効率性
このプロセスにおいて、EC2インスタンスプロファイル、IMDS
、IAM Role
、STS
サービスが連携して機能します。これにより:
- EC2インスタンスが安全かつ効率的に必要な認証情報を取得可能
- AWSリソースへのアクセスが可能になる
- EC2インスタンス上に長期的な認証情報を保存する必要がなくなり、セキュリティが向上
4. EC2からIMDS
をアクセスしてみる
IMDS
にはIDMSv1
とIDMSv2
という2つのバージョンがあります。
特徴 | IMDSv1 | IMDSv2 |
---|---|---|
認証 | 不要 | 時間制限のあるセッショントークンが必要 |
セキュリティ | 低 | 高 |
設定の複雑さ | 簡単 | やや複雑 |
AWS推奨 | ❌ | ⭕ |
IMDSv2
では、まずトークンを取得し、そのトークンを使用してメタデータにアクセスする2段階のプロセスを利用することによって、セキュリティが大幅に向上します。AWSはセキュリティ機能が強化されているIMDSv2
の使用を推奨しています。
EC2インスタンス作成する時に、V2のみとV1、V2両方サポートという2つの選択肢がありまして、デフォルトはV2のみです。
-
IMDSv1
の例:curl http://169.254.169.254/latest/meta-data/instance-id
-
IMDSv2
の例:TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id
-
AWSのSDKには、基本的なメタデータ情報をサポートする便利なコマンドラインツール
ec2-metadata
も付属しています。$ ec2-metadata --all ami-id: ami-07281c2a30e5bc1ab ami-launch-index: 0 ami-manifest-path: (unknown) ancestor-ami-ids: not available block-device-mapping: ami: xvda root: /dev/xvda instance-id: i-0c0d60ae77b6039c5 instance-type: t3.micro local-hostname: ip-10-0-0-165.ap-northeast-1.compute.internal local-ipv4: 10.0.0.165 kernel-id: not available placement: ap-northeast-1a product-codes: not available public-hostname: not available public-ipv4: not available public-keys: not available ramdisk-id: not available reservation-id: r-0ce0d554681d2d19d security-groups: ProviderVpcStack-WebSecurityGroup73AF7387-ZxdSh2HgIV3V user-data: #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd
興味深い点として、IMDS
はuser-data
の取得も可能であり、これを利用して任意のプロセスがスクリプトを実行できます。主要なOSでは、通常、cloud-init
が利用可能で、user-data
の取得と実行を処理します。
EC2インスタンス作成する時に、デフォルトとしてはIMDS
が有効になり、手動で無効化すると、以下の警告が表示される。つまりIMDS
が無効になると、インスタンス初回起動する時にuser dataが実行できない。
- 認証情報の取得について
IMDS
がEC2インスタンスに一時的な認証情報を提供しています。これは上記のec2-metadata
の属性には表示されていないため、curlを使用して取得する必要があります。認証情報を取得するにはRole名が必要です。これは手動で入力するか、メタデータ自体から簡単に取得できます。-
例えば、以下のようにしてRole名を取得できます。
$ ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
-
そして、そのRole名を使用して実際の認証情報を取得します。
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME { "Code" : "Success", "LastUpdated" : "2023-05-25T23:23:40Z", "Type" : "AWS-HMAC", "AccessKeyId" : "[redacted]", "SecretAccessKey" : "[redacted]", "Token" : "[redacted]", "Expiration" : "2024-09-06T13:53:03Z" }
-
この呼び出しにより、AccessKeyId
、SecretAccessKey
、Token
などの認証情報が返されます。これらの認証情報は、AWS CLIやSDKを使用してAWSリソースにアクセスする際に使用できます。
Token
の存在は、これがSTS(Security Token Service)
からの一時的な認証情報であることを示しています。これにより、EC2インスタンス上に認証情報を保存する必要なく、認証を機能させることができます。
5. まとめ
- EC2インスタンスはIMDSを通じて
IAM Role
の認証情報を取得 - このプロセスはAWS内部で完結し、外部ネットワークアクセスは不要
IMDS
とSTS
の通信はAWS内部で行われるため、VPCエンドポイントを明示的に作成する必要はありません<- セキュリティ機能が強化されている
IMDSv2
の使用を推奨