AWS Configルールを利用し、認証情報が一定期間未利用のIAMユーザーを無効化する前に事前通知する仕組み
はじめに
セキュリティ対策として、長期間使用されていないIAMユーザーの認証情報を定期的に無効化することは重要です。
AWS Configルール(iam-user-unused-credentials-check)とAWS Systems Manager オートメーションを利用することで、一定期間認証情報(アクセスキー・コンソールパスワード)が未利用のIAMユーザーの認証情報を自動で無効化できます。
一般的な運用として、例えば、90日以上未利用だった場合に無効化するケースが考えられます。
この場合、突然無効化されると利用者が困ってしまうため、事前に通知したい場合もあるでしょう。
本記事では、無効化の数日前に利用者や管理者に通知する方法を解説します。
システム構成
構成は以下のとおりです。
今回は、無効化予定日の7日前と14日前に段階的に通知したいと仮定します。この要件を実現するため、異なる日数パラメータを設定した2つのConfigルールを作成します。
2つのルールが必要な理由は、EventBridgeが準拠から非準拠への変更時に1回だけトリガーされるためです。つまり、各通知タイミング(7日前、14日前)で確実に1回ずつ通知するには、それぞれ専用のルールが必要になります。
ルールが非準拠となった場合、AWS Configのコンプライアンスステータス変更をトリガーに、EventBridge経由でAWS Step Functionsを起動し、Amazon SNSでメール通知を行います。
通知方法の選択肢
今回はSNSトピックで固定のメールアドレスに通知しますが、以下のような方法も可能です。
- IAMユーザーごとに個別通知:Amazon DynamoDBにIAMユーザー名と通知先メールアドレスを保存し、ステートマシンからAmazon SESなどで個別にメール送信
- 少数のユーザーの場合:ステートマシン内で直接ユーザーごとの通知先を定義
今回、SNSトピックは作成済みとします。
AWS Configルール作成
AWS Configルールを作成します。
AWSマネージド型ルールであるiam-user-unused-credentials-check
というルールを利用します。
ルール名をiam-credential-expiry-check-1
にし、パラメータmaxCredentialUsageAge
は83
に設定します。このパラメータは、指定した日数内に使用されていないパスワードまたはアクティブなアクセスキーがあるかどうかを確認します。つまり、いずれかの認証情報が83日以上非アクティブの場合、非準拠となります。
これで1つ目のルールが作成できました。
同様に、パラメータmaxCredentialUsageAge
を76
に設定したルール名iam-credential-expiry-check-2
を作成します。
これで2つのAWS Configルールが作成できました。
ステートマシン作成
以下のステートマシンを作成します。
maxUnusedDays
で90日での自動無効化期間を設定しています。
SNSトピックARNであるTopicArn
は各自変更してください。
{
"Comment": "IAMユーザー認証情報の自動無効化アラート通知ワークフロー - Config Rule評価結果に基づいて対象ユーザーにSNS通知を送信",
"QueryLanguage": "JSONata",
"StartAt": "Initialize Configuration",
"States": {
"Initialize Configuration": {
"Type": "Pass",
"Comment": "初期設定値を定義:AWSアカウントID、Config Rule名、最大未使用日数を設定",
"Assign": {
"awsAccountId": "{% $states.input.detail.awsAccountId %}",
"configRuleName": "{% $states.input.detail.configRuleName %}",
"maxUnusedDays": "{% 90 %}"
},
"Next": "Calculate Days"
},
"Calculate Days": {
"Type": "Pass",
"Comment": "ConfigRule名に基づいて残り日数を計算:check-1なら7日、check-2なら14日",
"Assign": {
"remainingDays": "{% $configRuleName = \"iam-credential-expiry-check-1\" ? 7 : $configRuleName = \"iam-credential-expiry-check-2\" ? 14 %}"
},
"Next": "Calculate Disable Deadline"
},
"Calculate Disable Deadline": {
"Type": "Pass",
"Comment": "無効化予定日を計算:現在日時 + 残り日数から YYYY/MM/DD 形式の文字列を生成",
"Assign": {
"disableDeadline": "{% (\n $remainingDays := (\n $configRuleName = \"iam-credential-expiry-check-1\" ? 7 :\n $configRuleName = \"iam-credential-expiry-check-2\" ? 14\n );\n $targetDate := $toMillis($now()) + ($remainingDays * 24 * 60 * 60 * 1000);\n $dateStr := $substring($fromMillis($targetDate), 0, 10);\n $replace($replace($dateStr, \"-\", \"/\"), /^(\\d{4})\\/(\\d{2})\\/(\\d{2})$/, \"$1/$2/$3\")\n) %}"
},
"Next": "ListUsers"
},
"ListUsers": {
"Comment": "全ユーザー一覧を取得し、ユーザーID(resourceId)に該当するユーザーの名前を特定",
"Arguments": {},
"Assign": {
"userName": "{% $states.result.Users[UserId=$states.input.detail.resourceId].UserName[0] %}"
},
"Next": "SNS Publish",
"Resource": "arn:aws:states:::aws-sdk:iam:listUsers",
"Type": "Task"
},
"SNS Publish": {
"Arguments": {
"TopicArn": "arn:aws:sns:ap-northeast-1:AWSアカウントID:cm-hirai",
"Subject": "{% 'IAM認証情報無効化通知 - ' & $userName %}",
"Message": "{% 'IAMユーザー「' & $userName & '」の認証情報(コンソールパスワード or アクセスキー)が' & $string($remainingDays) & '日後(' & $disableDeadline & ')に自動無効化されます。\n\n▼ 継続利用される場合の対応方法\n・AWSマネジメントコンソールへのログイン\n・アクセスキーを使用したAWS操作の実行\n\n※' & $string($maxUnusedDays) & '日間未使用の認証情報は、セキュリティ対策として自動無効化されます。\n\n■ 対象情報\n- AWSアカウントID: ' & $awsAccountId & '\n- IAMユーザー名: ' & $userName & '\n- 無効化予定日: ' & $disableDeadline & '\n- 残り日数: ' & $string($remainingDays) & '日\n\n本メールは自動送信されています。' %}"
},
"End": true,
"Resource": "arn:aws:states:::sns:publish",
"Type": "Task"
}
}
}
ステートマシンの動作は以下のとおりです。
- AWS ConfigルールからEventBridge経由で受け取ったイベントから、AWSアカウントIDとConfigルール名を取得
- Configルール名に基づいて残り日数を計算(check-1なら7日、check-2なら14日)
- 無効化予定日を計算してYYYY/MM/DD形式で生成
- IAM ListUsers APIを実行してリソースIDからユーザー名を特定
- SNS経由でメール通知を送信
ステートマシン作成時、IAMロールと一部のIAMポリシーも自動作成されます。
自動作成されないIAMポリシーは手動で作成し、IAMロールにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:ListUsers"
],
"Resource": "*"
}
]
}
EventBridge作成
EventBridgeルールを作成し、AWS Configのコンプライアンス変更イベントをトリガーとしてステートマシンを起動します。
イベントパターンは以下のように設定します。
{
"detail-type": ["Config Rules Compliance Change"],
"source": ["aws.config"],
"detail": {
"configRuleName": ["iam-credential-expiry-check-1", "iam-credential-expiry-check-2"],
"messageType": ["ComplianceChangeNotification"],
"newEvaluationResult": {
"complianceType": ["NON_COMPLIANT"]
}
}
}
ステータスが準拠から非準拠に変わった場合にトリガーされます。一度トリガーされた後もConfigルールで毎日チェックしますが、継続して非準拠の状態が続いても再度トリガーされることはありません。
EventBridgeルールのターゲット先は、先ほど作成したステートマシンに設定します。
作成の順番
EventBridgeルールとステートマシンを先に作成し、その後AWS Configルールを作成すると、76日や83日以上非アクティブのIAMユーザーが即座に非準拠となり、通知されてしまいます。
そのため、AWS Configルールを先に作成することをお勧めします。先にConfigルールを作成すると非準拠となりますが、その後EventBridgeルールとステートマシンを作成することで、EventBridgeはトリガーされません。その後、準拠から非準拠に変わったIAMユーザーのみがトリガーされ、通知されます。
作成する順番にはご注意ください。
実際に試してみる
実際に動作確認を行ったところ、以下のとおり通知されました。
ステートマシンが正常に動作し、期待どおりの通知メールが送信されていることが確認できました。
参考として、ステートマシンに渡されるEventBridgeイベントの例は以下のとおりです。
{
"version": "0",
"id": "3262a2d6-39ab-714f-158e-00d29af1402f",
"detail-type": "Config Rules Compliance Change",
"source": "aws.config",
"account": "アカウントID",
"time": "2025-07-30T07:21:24Z",
"region": "ap-northeast-1",
"resources": [],
"detail": {
"resourceId": "AIDATCKAQT2XMYOT37SQY",
"awsRegion": "ap-northeast-1",
"awsAccountId": "アカウントID",
"configRuleName": "iam-credential-expiry-check-2",
"recordVersion": "1.0",
"configRuleARN": "arn:aws:config:ap-northeast-1:アカウントID:config-rule/config-rule-ydinvr",
"messageType": "ComplianceChangeNotification",
"newEvaluationResult": {
"evaluationResultIdentifier": {
"evaluationResultQualifier": {
"configRuleName": "iam-credential-expiry-check-2",
"resourceType": "AWS::IAM::User",
"resourceId": "AIDATCKAQT2XMYOT37SQY",
"evaluationMode": "DETECTIVE"
},
"orderingTimestamp": "2025-07-30T07:20:49.600Z"
},
"complianceType": "NON_COMPLIANT",
"resultRecordedTime": "2025-07-30T07:21:24.168Z",
"configRuleInvokedTime": "2025-07-30T07:20:53.047Z"
},
"notificationCreationTime": "2025-07-30T07:21:24.867Z",
"resourceType": "AWS::IAM::User"
}
}
最後に
AWS Configルール、EventBridge、Step Functionsを組み合わせることで、IAMユーザーの認証情報無効化前の事前通知システムを構築できました。
この仕組みにより、利用者や管理者に対して十分な猶予期間を持って通知でき、突然のアクセス停止を防ぐことが可能です。セキュリティとユーザビリティの両方を考慮した運用が実現できます。