- AWS
CloudTrailで誰が操作したか調べる|lookup-eventsとAthena
直近 90 日の操作なら、CloudTrail の「イベント履歴」を aws cloudtrail lookup-events で検索すれば、誰が・いつ・どこから操作したかが分かります。 イベント履歴は、設定なしで記録されていて、見るのに CloudTrail の料金はかかりません。
90 日より前の操作や、S3 のオブジェクトの読み書き(データイベント)を調べるには、前もって「証跡(trail)」で S3 にログを保存し、Athena で SQL を使って検索します。
| 調べたいこと | 方法 | 条件 |
|---|---|---|
| 直近 90 日の管理イベント(作成・削除・設定変更・ログイン) | aws cloudtrail lookup-events |
1 回に1リージョン・条件は1つ |
| 90 日より前の操作 | 証跡+Athena | 証跡を作った後の分だけ |
| S3 のオブジェクト操作・Lambda の呼び出し(データイベント) | 証跡(データイベントを有効)+Athena | 有効にした後の分だけ。有料 |
| 複数の条件・複数リージョンをまとめて | Athena(または CloudTrail Lake) | 同上 |
| 例:知りたいこと | lookup-events の条件 |
|---|---|
| S3 バケットを誰が消したか | AttributeKey=EventName,AttributeValue=DeleteBucket |
| IAM の権限を誰が変えたか | AttributeKey=EventSource,AttributeValue=iam.amazonaws.com(us-east-1 で検索) |
| コンソールへのログイン履歴 | AttributeKey=EventName,AttributeValue=ConsoleLogin |
| 特定のユーザーの操作 | AttributeKey=Username,AttributeValue=taro |
| 特定のリソースへの操作 | AttributeKey=ResourceName,AttributeValue=リソース名 |
確認環境:AWS CLI 1.46.1・jq(Linux)。moto 5.2.4 は LookupEvents に対応していなかったため、CloudTrail の LookupEvents API と同じ形の応答を返すサーバーを手元に用意し、ドキュメントにあるイベントの形(userIdentity などの項目)で応答を作りました。そのうえで、CLI が送るリクエスト、--query・jq での整形、ページ送りを確かめています。証跡(trail)の作成・バケットポリシー・Athena の start-query-execution は moto のサーバーモードで通ることを確かめました。Athena のテーブル定義とクエリ、イベントの記録のされ方、料金は AWS のドキュメントに基づいて書いています(確認日 2026年10月12日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CloudTrailで誰が操作したか調べる|lookup-eventsとAthena」
lookup-events の基本
aws cloudtrail lookup-events \
--region ap-northeast-1 \
--lookup-attributes AttributeKey=EventName,AttributeValue=DeleteBucket \
--start-time 2026-10-01T00:00:00+09:00 \
--end-time 2026-10-13T00:00:00+09:00
| 決まり | 内容(ドキュメント) |
|---|---|
| 期間 | 直近 90 日まで |
| 対象 | 管理イベント(と CloudTrail Insights のイベント)。データイベントは入らない |
| リージョン | 1 回の検索で 1 つのリージョンだけ。--region で指定する |
| 条件 | --lookup-attributes は1つだけ。ほかは時刻の範囲だけ |
| 件数 | 1 回の応答で最大 50 件(既定 50)。続きは NextToken |
| 速さの上限 | アカウント・リージョンごとに 1 秒に 2 回 |
| 料金 | イベント履歴を見るのは無料 |
--lookup-attributes の AttributeKey に使える値です。
| AttributeKey | 意味 | 例 |
|---|---|---|
EventName |
API の名前 | DeleteBucket・TerminateInstances・ConsoleLogin |
EventSource |
サービス | s3.amazonaws.com・iam.amazonaws.com |
Username |
操作した人(IAM ユーザー名・ロールのセッション名など) | taro |
ResourceName |
リソース名・ID | my-bucket・i-0123456789abcdef0 |
ResourceType |
リソースの種類 | AWS::S3::Bucket・AWS::EC2::Instance |
AccessKeyId |
使われたアクセスキー | AKIAIOSFODNN7EXAMPLE |
ReadOnly |
読み取り操作か | false(変更だけ) |
EventId |
イベントの ID | — |
--lookup-attributes に2つ書くと、CLI はそのまま2つを送ります(手元のサーバーで、リクエストに2つ入っていることを確かめました)。API の決まりでは1つだけなので、2つ目の条件は jq で絞ります(後述)。
IAM・STS・CloudFront の操作は us-east-1 にある
ドキュメントでは、IAM・STS・CloudFront のようなグローバルサービスのイベントは、多くが 米国東部(バージニア北部)= us-east-1 で記録されます。東京リージョンで lookup-events しても、IAM の権限変更は出てきません。 --region us-east-1 を付けて検索します。
コンソールへのログイン(ConsoleLogin)も、記録されるリージョンが決まっています。
| ログインのしかた | 記録されるリージョン(ドキュメント) |
|---|---|
| ルートユーザー | us-east-1・us-east-2・us-west-2 のいずれか |
| IAM ユーザー(グローバルのサインイン、アカウントエイリアスの Cookie あり) | us-east-2・eu-north-1・ap-southeast-2 のいずれか |
| IAM ユーザー(グローバルのサインイン、Cookie なし) | us-east-1 |
| IAM ユーザー(リージョンのエンドポイント) | そのエンドポイントのリージョン |
ログイン履歴を漏れなく見るには、複数のリージョンを順に検索します。
for r in us-east-1 us-east-2 us-west-2 eu-north-1 ap-southeast-2 ap-northeast-1; do
echo "== $r"
aws cloudtrail lookup-events --region "$r" \
--lookup-attributes AttributeKey=EventName,AttributeValue=ConsoleLogin \
--start-time "$(date -d '30 days ago' +%F)" \
--output json \
| jq -r '.Events[].CloudTrailEvent | fromjson
| [.eventTime, .userIdentity.type, (.userIdentity.userName // .userIdentity.arn),
.sourceIPAddress, .responseElements.ConsoleLogin, .additionalEventData.MFAUsed] | @tsv'
done
目的別コマンド集
誰が消したか
| 消えたもの | EventName | EventSource |
|---|---|---|
| S3 バケット | DeleteBucket |
s3.amazonaws.com |
| EC2 インスタンス | TerminateInstances |
ec2.amazonaws.com |
| EBS ボリューム・スナップショット | DeleteVolume・DeleteSnapshot |
ec2.amazonaws.com |
| RDS インスタンス | DeleteDBInstance |
rds.amazonaws.com |
| DynamoDB テーブル | DeleteTable |
dynamodb.amazonaws.com |
| セキュリティグループのルール | RevokeSecurityGroupIngress |
ec2.amazonaws.com |
| IAM ユーザー・ロール | DeleteUser・DeleteRole(us-east-1) |
iam.amazonaws.com |
S3 のオブジェクト(ファイル)の削除 DeleteObject はデータイベントなので、イベント履歴には出ません。 証跡でデータイベントを有効にしていた場合だけ、Athena で探せます。
リソース名が分かっているなら、ResourceName で探すのが確実です。
aws cloudtrail lookup-events --region ap-northeast-1 \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=my-old-bucket \
--output json \
| jq '.Events[] | .CloudTrailEvent | fromjson
| {time: .eventTime, event: .eventName, who: .userIdentity.arn,
role: .userIdentity.sessionContext.sessionIssuer.userName,
ip: .sourceIPAddress, key: .userIdentity.accessKeyId}'
手元のサーバーで、ロールを引き受けた(AssumedRole)利用者がバケットを消したイベントを返したときの出力です(アクセスキーなどはドキュメントの例の値)。
{
"time": "2026-10-12T01:23:45Z",
"event": "DeleteBucket",
"who": "arn:aws:sts::123456789012:assumed-role/DevRole/hanako",
"role": "DevRole",
"ip": "203.0.113.10",
"key": "ASIAIOSFODNN7EXAMPLE"
}
誰が権限を変えたか(IAM)
aws cloudtrail lookup-events --region us-east-1 \
--lookup-attributes AttributeKey=EventSource,AttributeValue=iam.amazonaws.com \
--start-time "$(date -d '14 days ago' +%F)" \
--output json \
| jq -r '.Events[].CloudTrailEvent | fromjson
| select(.readOnly == false)
| select(.eventName | test("^(Attach|Detach|Put|Delete)(User|Role|Group)Policy$|^CreatePolicyVersion$|^SetDefaultPolicyVersion$|^UpdateAssumeRolePolicy$|^AddUserToGroup$|^CreateAccessKey$|^CreateLoginProfile$"))
| [.eventTime, .eventName, .userIdentity.arn,
(.requestParameters.roleName // .requestParameters.userName // .requestParameters.groupName // "-"),
(.requestParameters.policyArn // .requestParameters.policyName // "-")] | @tsv'
| EventName | 意味 |
|---|---|
AttachRolePolicy・AttachUserPolicy・AttachGroupPolicy |
管理ポリシーを付けた |
PutRolePolicy・PutUserPolicy・PutGroupPolicy |
インラインポリシーを付けた・変えた |
CreatePolicyVersion・SetDefaultPolicyVersion |
管理ポリシーの中身を変えた |
UpdateAssumeRolePolicy |
ロールの信頼ポリシーを変えた(誰が引き受けられるか) |
AddUserToGroup |
グループに入れた(グループの権限が付く) |
CreateAccessKey・CreateLoginProfile |
アクセスキー・コンソールのパスワードを作った |
ポリシーの種類の違いは、関連記事「IAM管理ポリシーとインラインポリシーの違い|CLIで確認・アタッチ」で扱っています。
特定のユーザーの操作(変更だけ)
aws cloudtrail lookup-events --region ap-northeast-1 \
--lookup-attributes AttributeKey=Username,AttributeValue=taro \
--query 'Events[].[EventTime,EventName,Resources[0].ResourceName]' \
--output text
変更の操作だけに絞るなら、ReadOnly=false で検索し、jq でユーザーを絞ります(条件は1つしか送れないため)。
aws cloudtrail lookup-events --region ap-northeast-1 \
--lookup-attributes AttributeKey=ReadOnly,AttributeValue=false \
--start-time "$(date -d '1 day ago' +%FT%T)" \
--output json \
| jq -r '.Events[] | select(.Username == "taro")
| [.EventName, (.Resources[0].ResourceName // "-")] | @tsv'
アクセスキーが漏れたとき:そのキーで何をされたか
aws cloudtrail lookup-events --region ap-northeast-1 \
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE \
--output json \
| jq -r '.Events[].CloudTrailEvent | fromjson
| [.eventTime, .awsRegion, .eventName, .sourceIPAddress, (.errorCode // "OK")] | @tsv'
リージョンごとに記録されるので、使っていないリージョンも含めて全部を検索します。 リージョンの一覧は aws ec2 describe-regions --query 'Regions[].RegionName' --output text で取れます。アクセスキーの無効化とローテーションは、関連記事「IAMアクセスキーの作成・確認・ローテーション手順 CLI版」で扱っています。
出力の読み方
lookup-events の応答は、Events の配列です。
| 項目 | 意味 |
|---|---|
EventId |
イベントの ID |
EventName |
API の名前 |
EventTime |
発生時刻 |
EventSource |
サービス(s3.amazonaws.com など) |
Username |
操作した人の名前(ロールならセッション名) |
Resources |
対象のリソース(ResourceType・ResourceName) |
AccessKeyId |
使われたアクセスキー |
ReadOnly |
読み取りか("true"・"false" の文字列) |
CloudTrailEvent |
イベントの全体。JSON が「文字列」として入っている |
詳しい情報は CloudTrailEvent の中にあります。 文字列なので、jq の fromjson で JSON に戻してから読みます。--query(JMESPath)では、この文字列の中は読めません。
CloudTrailEvent の主な項目
| 項目 | 意味 | 調査での見方 |
|---|---|---|
userIdentity |
誰が(種類・ARN・アクセスキーなど) | 下の表 |
eventTime |
いつ(UTC、ISO 8601) | 日本時間は +9 時間 |
eventSource・eventName |
何を | — |
awsRegion |
どのリージョンで | — |
sourceIPAddress |
どこから(IP アドレス) | AWS のサービスが代わりに呼んだときは、サービス名が入ることがある |
userAgent |
何を使って(コンソール・CLI・SDK) | aws-cli/...・Boto3/... など |
requestParameters |
送られたパラメータ | 消したバケット名・付けたポリシーの ARN など |
responseElements |
返った結果 | ConsoleLogin: Success/Failure など |
errorCode・errorMessage |
失敗した理由 | AccessDenied など。失敗した操作も記録される |
readOnly |
読み取りか | 変更だけを見るなら false |
recipientAccountId |
記録したアカウント | 他のアカウントからの操作の確認 |
userIdentity の type ごとの「誰か」
userIdentity.type |
意味(ドキュメント) | 人を特定する項目 |
|---|---|---|
Root |
ルートユーザー | arn(...:root) |
IAMUser |
IAM ユーザーの認証情報 | userName・arn・accessKeyId |
AssumedRole |
ロールを引き受けた一時的な認証情報 | arn の最後(セッション名)、sessionContext.sessionIssuer.userName(ロール名)、sessionContext.sourceIdentity |
IdentityCenterUser |
IAM Identity Center のユーザーの代わりに行った操作 | onBehalfOf.userId・onBehalfOf.identityStoreArn |
FederatedUser |
GetFederationToken の一時的な認証情報 |
principalId・arn |
AWSService |
AWS のサービスが行った操作 | invokedBy |
AWSAccount |
別のアカウントからの操作 | accountId |
AssumedRole のイベントには、人の名前が直接は入りません。 ARN の最後のセッション名(例 arn:aws:sts::123456789012:assumed-role/DevRole/hanako の hanako)や、sourceIdentity を設定していればその値で人をたどります。ロールの仕組みは、関連記事「IAMロールとは|ユーザー・ポリシーとの違いとAssumeRole、信頼ポリシー」で扱っています。
ドキュメントにあるコンソールログイン失敗のイベント(一部)です。
{
"userIdentity": {
"type": "IAMUser",
"accountId": "123456789012",
"accessKeyId": "",
"userName": "Paulo"
},
"eventSource": "signin.amazonaws.com",
"eventName": "ConsoleLogin",
"awsRegion": "us-east-1",
"sourceIPAddress": "192.0.2.0",
"errorMessage": "Failed authentication",
"responseElements": {
"ConsoleLogin": "Failure"
},
"additionalEventData": {
"MobileVersion": "No",
"MFAUsed": "Yes"
},
"eventType": "AwsConsoleSignIn",
"eventCategory": "Management"
}
jq で一覧にする
手元のサーバーで、3件のイベント(ドキュメントの形で作成)を返したときの出力です。
aws cloudtrail lookup-events --output json \
| jq -r '.Events[] | .CloudTrailEvent | fromjson
| [.eventTime, .eventName, .userIdentity.type, .userIdentity.arn, .sourceIPAddress] | @tsv'
2026-10-12T01:23:45Z DeleteBucket AssumedRole arn:aws:sts::123456789012:assumed-role/DevRole/hanako 203.0.113.10
2026-10-11T09:02:11Z TerminateInstances IAMUser arn:aws:iam::123456789012:user/taro 198.51.100.24
2026-10-10T05:40:00Z AttachRolePolicy IAMUser arn:aws:iam::123456789012:user/taro 198.51.100.24
日本時間で見たいときは、jq で変換します。この記事の jq のレシピ(日本時間への変換・IAM の変更の抽出・ユーザーでの絞り込み・アクセスキーでの検索)は、手元のサーバーの応答で動くことを確かめています。
jq -r '.Events[].CloudTrailEvent | fromjson
| [(.eventTime | fromdateiso8601 + 9*3600 | strftime("%Y-%m-%d %H:%M:%S JST")), .eventName, .userIdentity.arn] | @tsv'
--query と --output table で表にした結果です(CLI の設定で cli_timestamp_format = iso8601 にした場合)。
--------------------------------------------------------------------------------------
| LookupEvents |
+---------------------------+----------------------+---------+-----------------------+
| 2026-10-12T10:23:45+09:00| DeleteBucket | hanako | my-old-bucket |
| 2026-10-11T18:02:11+09:00| TerminateInstances | taro | i-0123456789abcdef0 |
| 2026-10-10T14:40:00+09:00| AttachRolePolicy | taro | app-role |
+---------------------------+----------------------+---------+-----------------------+
AWS CLI v1 は、何も設定しないと EventTime を 1791768225.0 のような UNIX 時間の数値で表示しました。 ~/.aws/config に cli_timestamp_format = iso8601 を書くと、上のように ISO 8601 になります。AWS CLI v2 は既定で ISO 8601 です。jq で読むなら、CloudTrailEvent の中の eventTime(いつも ISO 8601 の文字列)を使うと、CLI の版に左右されません。
jq の書き方は、関連記事「jqの使い方|逆引き40例と実務レシピを全部実行結果つきで解説」で扱っています。
ページ送りと件数
AWS CLI は lookup-events のページ送りを自動で行い、全件を取ってきます。件数を区切るなら --max-items を使います。
aws cloudtrail lookup-events --max-items 2 \
--query '[Events[].EventName, NextToken]' --output json
[
[
"DeleteBucket",
"TerminateInstances"
],
"eyJOZXh0VG9rZW4iOiBudWxsLCAiYm90b190cnVuY2F0ZV9hbW91bnQiOiAyfQ=="
]
続きは --starting-token に NextToken の値を渡して取ります。API は 1 秒に 2 回までなので、期間を広く取ると時間がかかります。--start-time と --end-time で期間を絞ってから検索すると速くなります。
90 日を超える調査:証跡(trail)+Athena
イベント履歴は 90 日で消えます。 それより前を調べるには、事前に証跡を作り、S3 にログを残しておく必要があります。証跡は、作った後のイベントしか保存しません。 調べたくなってから作っても、過去の分は戻りません。
証跡の作成
| 項目 | 料金(料金ページ) |
|---|---|
| イベント履歴の閲覧 | 無料 |
| 管理イベントの最初のコピーを S3 に送る | 無料 |
| 管理イベントの追加のコピー | 10 万件あたり $2.00 |
| データイベント | 10 万件あたり $0.10 |
| S3 の保存・Athena の検索 | それぞれのサービスの料金 |
S3 バケットのポリシー(ドキュメントの形)です。ACCOUNT_ID・REGION・TRAIL・BUCKET を自分の値にします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck20150319",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::BUCKET",
"Condition": {"StringEquals": {"aws:SourceArn": "arn:aws:cloudtrail:REGION:ACCOUNT_ID:trail/TRAIL"}}
},
{
"Sid": "AWSCloudTrailWrite20150319",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::BUCKET/AWSLogs/ACCOUNT_ID/*",
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceArn": "arn:aws:cloudtrail:REGION:ACCOUNT_ID:trail/TRAIL"}}
}
]
}
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=ap-northeast-1
BUCKET=my-cloudtrail-logs-$ACCOUNT_ID
TRAIL=account-audit
aws s3api create-bucket --bucket "$BUCKET" \
--create-bucket-configuration LocationConstraint=$REGION
aws s3api put-bucket-policy --bucket "$BUCKET" --policy file://bucket-policy.json
# 全リージョン・グローバルサービスのイベントを1つの証跡で
aws cloudtrail create-trail --name "$TRAIL" --s3-bucket-name "$BUCKET" \
--is-multi-region-trail --include-global-service-events \
--enable-log-file-validation
aws cloudtrail start-logging --name "$TRAIL"
aws cloudtrail get-trail-status --name "$TRAIL" --query IsLogging
moto で動かすと、create-trail は IsMultiRegionTrail・IncludeGlobalServiceEvents・LogFileValidationEnabled がすべて True の証跡を返し、get-trail-status の IsLogging は true でした。create-trail だけでは記録が始まらず、start-logging が要ります。
--enable-log-file-validation は、ログファイルが書き換えられていないかを、あとで確かめられるようにする設定です。S3 のバケットポリシーの書き方は、関連記事「S3バケットポリシーの書き方と例 IP制限・Condition早見表」で扱っています。
ログは、S3 の AWSLogs/アカウントID/CloudTrail/リージョン/年/月/日/ の下に保存されます。
Athena のテーブル(パーティション射影)
ドキュメントにある、パーティション射影(partition projection)を使うテーブル定義です。日付のパーティションを自動で扱うので、ALTER TABLE ADD PARTITION が要りません。 LOCATION と storage.location.template のバケット名・アカウント ID・リージョンを書き換えます。
CREATE EXTERNAL TABLE cloudtrail_logs_pp(
eventversion STRING,
useridentity STRUCT<
type: STRING,
principalid: STRING,
arn: STRING,
accountid: STRING,
invokedby: STRING,
accesskeyid: STRING,
username: STRING,
onbehalfof: STRUCT<
userid: STRING,
identitystorearn: STRING>,
sessioncontext: STRUCT<
attributes: STRUCT<
mfaauthenticated: STRING,
creationdate: STRING>,
sessionissuer: STRUCT<
type: STRING,
principalid: STRING,
arn: STRING,
accountid: STRING,
username: STRING>,
ec2roledelivery:string,
webidfederationdata: STRUCT<
federatedprovider: STRING,
attributes: map<string,string>>
>
>,
eventtime STRING,
eventsource STRING,
eventname STRING,
awsregion STRING,
sourceipaddress STRING,
useragent STRING,
errorcode STRING,
errormessage STRING,
requestparameters STRING,
responseelements STRING,
additionaleventdata STRING,
requestid STRING,
eventid STRING,
readonly STRING,
resources ARRAY<STRUCT<
arn: STRING,
accountid: STRING,
type: STRING>>,
eventtype STRING,
apiversion STRING,
recipientaccountid STRING,
serviceeventdetails STRING,
sharedeventid STRING,
vpcendpointid STRING,
vpcendpointaccountid STRING,
eventcategory STRING,
addendum STRUCT<
reason:STRING,
updatedfields:STRING,
originalrequestid:STRING,
originaleventid:STRING>,
sessioncredentialfromconsole STRING,
edgedevicedetails STRING,
tlsdetails STRUCT<
tlsversion:STRING,
ciphersuite:STRING,
clientprovidedhostheader:STRING>
)
PARTITIONED BY (
`timestamp` string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
's3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region'
TBLPROPERTIES (
'projection.enabled'='true',
'projection.timestamp.format'='yyyy/MM/dd',
'projection.timestamp.interval'='1',
'projection.timestamp.interval.unit'='DAYS',
'projection.timestamp.range'='2020/01/01,NOW',
'projection.timestamp.type'='date',
'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region/${timestamp}')
| 書き換える所 | 内容 |
|---|---|
amzn-s3-demo-bucket |
証跡のバケット名 |
account-id |
アカウント ID |
aws-region |
リージョン(例 ap-northeast-1) |
projection.timestamp.range の開始日 |
ログを残し始めた日。ドキュメントの例は 2020/01/01 |
このテーブルは1つのリージョン分です。 IAM などのグローバルサービスのイベントは us-east-1 の下に入るので、aws-region を us-east-1 にしたテーブル(例 cloudtrail_logs_use1)も作っておきます。
検索では、WHERE に必ず timestamp(日付のパーティション)を入れます。 入れないと全期間を読み、検索の料金と時間が増えます。
Athena のクエリ例
誰が消したか(期間を指定)
SELECT eventtime,
eventname,
useridentity.type AS who_type,
useridentity.arn AS who,
sourceipaddress,
json_extract_scalar(requestparameters, '$.bucketName') AS bucket
FROM cloudtrail_logs_pp
WHERE timestamp BETWEEN '2026/01/01' AND '2026/06/30'
AND eventname IN ('DeleteBucket', 'TerminateInstances', 'DeleteDBInstance', 'DeleteTable', 'DeleteVolume')
ORDER BY eventtime DESC;
ドキュメントには、resources の配列を UNNEST して、消されたバケットの名前を取り出す例があります。
SELECT
awsregion,
replace(unnested.resources_entry.ARN,'arn:aws:s3:::') as deleted_bucket,
eventtime AS time_deleted,
useridentity.username,
unnested.resources_entry.accountid as bucket_acct_id
FROM cloudtrail_logs t
CROSS JOIN UNNEST(t.resources) unnested (resources_entry)
WHERE eventname = 'DeleteBucket'
ORDER BY eventtime
(ドキュメントの例はテーブル名が cloudtrail_logs です。上のテーブル定義を使うなら cloudtrail_logs_pp にし、timestamp の条件を足します。)
誰が IAM の権限を変えたか(us-east-1 のテーブル)
SELECT eventtime,
eventname,
useridentity.arn AS who,
sourceipaddress,
coalesce(json_extract_scalar(requestparameters, '$.roleName'),
json_extract_scalar(requestparameters, '$.userName'),
json_extract_scalar(requestparameters, '$.groupName')) AS target,
json_extract_scalar(requestparameters, '$.policyArn') AS policy_arn
FROM cloudtrail_logs_use1
WHERE timestamp >= '2026/04/01'
AND eventsource = 'iam.amazonaws.com'
AND readonly = 'false'
AND errorcode IS NULL
ORDER BY eventtime DESC
LIMIT 200;
コンソールへのログイン履歴(失敗も含む)
SELECT eventtime,
useridentity.type,
coalesce(useridentity.username, useridentity.arn) AS who,
sourceipaddress,
json_extract_scalar(responseelements, '$.ConsoleLogin') AS result,
json_extract_scalar(additionaleventdata, '$.MFAUsed') AS mfa,
errormessage
FROM cloudtrail_logs_use1
WHERE timestamp >= '2026/07/01'
AND eventname = 'ConsoleLogin'
ORDER BY eventtime DESC;
特定の人(ロールのセッション名)の変更操作
SELECT eventtime, awsregion, eventsource, eventname, sourceipaddress, errorcode
FROM cloudtrail_logs_pp
WHERE timestamp BETWEEN '2026/09/01' AND '2026/09/30'
AND useridentity.arn LIKE '%/hanako'
AND readonly = 'false'
ORDER BY eventtime;
権限がなくて失敗した操作
SELECT useridentity.arn AS who, eventsource, eventname, errorcode, count(*) AS n
FROM cloudtrail_logs_pp
WHERE timestamp >= '2026/10/01'
AND errorcode IN ('AccessDenied', 'AccessDeniedException', 'Client.UnauthorizedOperation')
GROUP BY 1, 2, 3, 4
ORDER BY n DESC
LIMIT 50;
CLI からクエリを実行する
QID=$(aws athena start-query-execution \
--work-group primary \
--query-execution-context Database=default \
--result-configuration OutputLocation=s3://my-athena-results/ \
--query-string "SELECT eventtime, eventname, useridentity.arn FROM cloudtrail_logs_pp WHERE timestamp >= '2026/10/01' AND eventname = 'DeleteBucket'" \
--query QueryExecutionId --output text)
aws athena get-query-execution --query-execution-id "$QID" \
--query 'QueryExecution.Status.State' --output text # SUCCEEDED になるまで待つ
aws athena get-query-results --query-execution-id "$QID" \
--query 'ResultSet.Rows[].Data[].VarCharValue' --output text
requestparameters などは JSON の文字列として入っているので、json_extract_scalar(列, '$.キー') で値を取り出します。useridentity は構造体なので、useridentity.arn のように . でたどれます。
CloudTrail Lake の位置づけ
CloudTrail Lake は、イベントを専用の保存先(イベントデータストア)に集め、SQL で検索できる CloudTrail の機能です。 Athena と違って S3 のバケットやテーブル定義を用意せず、複数のリージョン・アカウントをまとめて検索できます。
| 項目 | イベント履歴 | 証跡+Athena | CloudTrail Lake |
|---|---|---|---|
| 期間 | 90 日 | S3 に残す限り | 最大 3,653 日(約10年)または 2,557 日(約7年)。料金の選択肢による |
| 検索 | 条件1つ+時刻 | SQL | SQL(Trino の SELECT) |
| 複数リージョン | 1 回に1つ | テーブルの作り方次第 | まとめて |
| 準備 | なし | 証跡・バケット・テーブル | イベントデータストア |
| 料金 | 無料 | S3 の保存・Athena のスキャン量 | 取り込み・保存・スキャン量 |
| 新規の利用 | — | — | 2026年5月31日から、新しい利用者は使い始められない(既存の利用者はそのまま使える) |
ドキュメントでは、CloudTrail Lake は 2026年5月31日以降、新しい利用者を受け付けないとされています。これから長期の調査の仕組みを作るなら、証跡+Athena が使える方法です。
よくある質問
Q. lookup-events で何も出ません。
A. リージョンを確かめます。IAM・STS・CloudFront の操作は主に us-east-1、コンソールのログインは表のリージョンに記録されます。90 日より前の操作や、S3 の GetObject・PutObject・DeleteObject のようなデータイベントは出ません。
Q. 操作した IP アドレスが ec2.amazonaws.com のようなサービス名になっています。
A. AWS のサービスが利用者の代わりに API を呼んだときは、sourceIPAddress にサービス名が入ることがあります。userIdentity.invokedBy も合わせて見ます。
Q. 失敗した操作も記録されますか。
A. 記録されます。errorCode・errorMessage に理由が入ります。AccessDenied が続いている利用者は、権限を探っている可能性もあるので確かめます。
Q. コンソールでの操作と CLI での操作は見分けられますか。
A. userAgent を見ます。CLI なら aws-cli/...、SDK なら Boto3/... などが入ります。
Q. 証跡のログは改ざんされていないと言えますか。
A. --enable-log-file-validation を有効にしておくと、aws cloudtrail validate-logs でログファイルが書き換えられていないかを確かめられます。
まとめ
- 直近 90 日の管理イベントは
aws cloudtrail lookup-events(無料)。条件は1つ・1 リージョン・1 秒 2 回 - IAM の変更は us-east-1 で検索する。ログインはルートか IAM ユーザーかで記録先が変わる
- 詳細は
CloudTrailEvent(文字列)を jq のfromjsonで読む。誰かはuserIdentity、どこからはsourceIPAddress - AssumedRole は ARN の最後のセッション名・
sessionIssuer・sourceIdentityで人をたどる - 90 日を超える・データイベントを見るなら、事前に証跡(
create-trail+start-logging)を作り、Athena でtimestampを絞って SQL - CloudTrail Lake は 2026年5月31日から新規の利用者は使い始められない
参考・出典
確認日はいずれも 2026年10月12日です。
- AWS CloudTrail API リファレンス「LookupEvents」:https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_LookupEvents.html
- AWS CLI コマンドリファレンス「lookup-events」:https://docs.aws.amazon.com/cli/latest/reference/cloudtrail/lookup-events.html
- AWS CloudTrail ユーザーガイド「Working with CloudTrail event history」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html
- AWS CloudTrail ユーザーガイド「CloudTrail concepts(Global service events)」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html
- AWS CloudTrail ユーザーガイド「CloudTrail userIdentity element」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html
- AWS CloudTrail ユーザーガイド「AWS Management Console sign-in events」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-aws-console-sign-in-events.html
- AWS CloudTrail ユーザーガイド「Amazon S3 bucket policy for CloudTrail」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html
- AWS CloudTrail ユーザーガイド「Working with AWS CloudTrail Lake」:https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-lake.html
- AWS CloudTrail の料金:https://aws.amazon.com/cloudtrail/pricing/
- Amazon Athena ユーザーガイド「Create the table for CloudTrail logs in Athena using partition projection」:https://docs.aws.amazon.com/athena/latest/ug/create-cloudtrail-table-partition-projection.html
- Amazon Athena ユーザーガイド「Example CloudTrail log queries」:https://docs.aws.amazon.com/athena/latest/ug/query-examples-cloudtrail-logs.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CloudTrailで誰が操作したか調べる|lookup-eventsとAthena」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。