STS エンドポイントを無効化した状態で IAM ロールが必要なアクションを実行してみた

絞めた元栓は、利用開始前にまた開きましょう
2023.04.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

アノテーション、テクニカルサポートチームの村上です。

以前、普段は利用していない AWS リージョンで Amazon Redshift の利用を始めたお客様から、IAM サービスロールを Redshift で受け取れないためエラーが発生するというお問い合わせをいただいたことがありました。
Redshift がクエリ実行に必要な IAM サービスロールを受け取れなかった原因は、ご利用の Redshift が存在するリージョンの STS エンドポイントが無効になっていたことによるものでした。
本記事では、十分な権限を持つ Glue Crawler を STS エンドポイントを無効化したリージョンでクロールさせてみて、どのようなエラーが発生しエラー内容から原因まで特定することができるかについて考えてみます。

試してみること

以下の手順で検証をしてみます。

1. S3 をオレゴンリージョンで作成
2. IAM サービスロール AWSGlueServiceRole-test20230423 を Glue Crawler にアタッチ
3. オレゴンリージョンの STS エンドポイントを無効化
4. STS エンドポイントが無効化された状況でクロールを実行
5. クロールの実行結果と CloudWatch Logs 等からクロール失敗の原因を特定できるか確認
6. オレゴンリージョンの STS エンドポイントを有効化
7. クロールが成功しログストリームと Glue テーブルが作成されるかを確認

いきなりまとめ

STS エンドポイントをリージョンごとに有効化・無効化できることを知らなくても、CloudTrail イベント履歴から STS エンドポイントが無効化されていることにより IAM ロールの呼び出しができないことを特定することは可能です。

設定時ハマりポイント

AWSGlueServiceRole ポリシーをそのまま利用する場合、Glue Crawler のクロール対象となる S3 バケットの名前は、aws-glue-で始まる必要があります。
ステップ 1: AWS Glue サービスの IAM ポリシーを作成する

クローラやジョブに関するサンプル、もしくはチュートリアルで使用されている、Amazon S3 オブジェクトの取得を許可します。命名規則: Amazon S3 バケット名は 「crawler-public」および「aws-glue-」で始まります。

私は、二度このトラップ?にかかったことがあります。
さすがに二度目は、わりとすぐにクロール対象となる S3 バケット名に命名規則があったことを思い出しましたが、一度目はどうしてクロールが失敗するのか原因が分からずかなりの時間アレコレ調べていました。
なぜバケット名が aws-glue- から始まる必要があるかについては、以下の AWSGlueServiceRole ポリシーの"Resource"フィールドに注目していただければと思います。
もちろん、バケット名に合わせてポリシーの方を書き直していただいても大丈夫です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "glue:*",
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:ListAllMyBuckets",
                "s3:GetBucketAcl",
                "ec2:DescribeVpcEndpoints",
                "ec2:DescribeRouteTables",
                "ec2:CreateNetworkInterface",
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcAttribute",
                "iam:ListRolePolicies",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "cloudwatch:PutMetricData"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket"
            ],
            "Resource": [
                "arn:aws:s3:::aws-glue-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::aws-glue-*/*",
                "arn:aws:s3:::*/*aws-glue-*/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::crawler-public*",
                "arn:aws:s3:::aws-glue-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:/aws-glue/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags",
                "ec2:DeleteTags"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "aws-glue-service-resource"
                    ]
                }
            },
            "Resource": [
                "arn:aws:ec2:*:*:network-interface/*",
                "arn:aws:ec2:*:*:security-group/*",
                "arn:aws:ec2:*:*:instance/*"
            ]
        }
    ]
}

下準備

1. オレゴンリージョンで S3 を作成する

バケット名:aws-glue-sts-test-20230423
リージョン:オレゴン (us-west-2)

フォルダ test20230423 を作成した後に CSV ファイル 202304023memberlist.csv を格納しました。

2. オレゴンリージョンで Glue クローラーを作成する

AWS Glue を選択した後、マネジメントコンソールの左ペインから「Crawlers」を選択し、「Create crawler」ボタンをクリックします。

クローラー名に testcrawler20230423 と入力して、「Next」ボタンを押下します。

「Add a data source」ボタンを押下します。


クローラーがクロールするリソースを指定します。
ここでは、先ほど作成した S3 バケット aws-glue-sts-test-20230423 を指定しています。

次は、権限周りの設定です。
クローラーへアタッチする IAM サービスロールを作成していないので、「Create new IAM role」ボタンを押下して、IAM ロールを作成します。

IAM ロールの名前は、AWSGlueServiceRole-test20230423 としました。

IAM ロール AWSGlueServiceRole-test20230423 には、おそらくクロールに必要な 2 つのポリシー(AWSGlueServiceRole-test20230423-EZCRC-s3Policy と AWSGlueServiceRole)がアタッチされていました。
この辺りは、マネジメントコンソール上の表示に従って進めている感じなので、ポリシー内容についてはあまり気にせず十分な権限は付与されるものとして進めていきます。

いちおう IAM ロール AWSGlueServiceRole-test20230423 の信頼されたエンティティが Glue であることを確認しておきます。
この IAM ロールを、サービス Glue が利用できることを確認できました。


クロールに必要な IAM ロールと IAM ポリシーは作成できたので、「Next」ボタンを押下します。

次は、AWS Glue Data Catalog において、テーブルのコンテナとなるデータベースを作成します。


データベース名を test20230423 としました。
クローラーがクロールに成功すれば、データベース test20230423 内に新しい Glue Data Catalog テーブルが作成されます。


レビュー画面で全ての設定が反映されていることを確認してから「Create crawler」ボタンを押下して、クローラーを作成します。

以上で、下準備は終わりです。お疲れ様でした!

STS エンドポイントを無効化してみた

サービス IAM を選択した後、マネジメントコンソールの左ペインから「アカウント設定」を選択し、オレゴンリージョンの STS エンドポイントを非アクティブ化します。

Crawler を実行してみた

クローラーを実行してみます。
STS エンドポイントが無効となっているので、クローラーが IAM ロール AWSGlueServiceRole-test20230423 を受け取ることができずクロールに失敗するはずです。

想定どおりクロールに失敗しました。

クロール失敗の原因を確かめてみた

ここからは、STS エンドポイントが無効になっていることがクロール失敗の原因であることに気づけるかどうかを考えてみます。

何かのアクションが失敗したり、障害が発生した場合は、まずログを確認することが重要です。
クローラーを実行したマネジメントコンソール上に、ログへのリンクがあるので、そのリンクをクリックして CloudWatch Logs 画面に移動してみます。

クロールが失敗したにもかかわらず、ログストリームが作成されていませんでした。
IAM ポリシー AWSGlueServiceRole には、以下の記述があるのでログが作成されるはずですが、どういうことでしょうか?
なお、ロググループについては以前の検証時に作成されたものが残っていたため、ここではログストリームが作成されなかったことを手掛かりとします。

        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:/aws-glue/*"
            ]
        },

IAM ロール AWSGlueServiceRole-test20230423 の信頼されたエンティティが Glue では無かった為に、ロールを受け取れなかった可能性も考えられますが、以下のように信頼されたエンティティに Glue が指定されていることも確認できます。

CloudWatch Logs と IAM ロールを中心にクロール失敗の原因を考えるとこの辺りで手詰まりになりそうですが、何か大切なことを忘れている気が、、、
そう、こんな時に頼りになるのが CloudTrail です。

AWS CloudTrail による IAM および AWS STS の API コールのログ記録

IAM および AWS STS は AWS CloudTrail と統合されています。このサービスは、IAM ユーザーやロールのサービスによって実行されたアクションを記録するサービスです。CloudTrail は、コンソールからの呼び出しや API 呼び出しを含む、IAM と AWS STS のすべての API 呼び出しをイベントとしてキャプチャします。

クロールが失敗した日時の AssumeRole 履歴を調べたところ、以下のイベントを発見することができました!

"errorCode": "RegionDisabledException"
"errorMessage": "STS is not activated in this region for account:************. Your account administrator can activate STS in this region using the IAM Console."

このエラーメッセージを発見できれば、STS がリージョンごとに無効化できることを知らなくてもクロール失敗の原因と対応まで分かりますね。

STS エンドポイントを有効化してみた

オレゴンリージョンの STS エンドポイントを有効化して、ちゃんとクロールに成功するかを確かめておきます。

STS エンドポイントは有効となっているので、他の設定に問題が無ければ成功するはず。

他の設定も問題が無かったみたいで、クロールに成功しました!

ログストリームが作成されているかも確認してみます。
ログストリーム testcrawler20230423 が作成されていました。

最後に、クロールが成功したことで Glue Data Catalog テーブルが作成されているかを確認してみます。
Glue Data Catalog テーブル「aws_glue_sts_test_20230423」が作成されていることを確認できました。

まとめ

普段利用していないリージョンでサービスを使い始めて、本記事と同じような事象が発生したらそのリージョンの STS エンドポイントが無効化されていないか確認してみてください。
この記事がどなたかのお役に立てば幸いです。

参考資料