Tools · AWS detection and investigation · 07 / 24
CloudTrail Lake: query status, pages, and the note
Read QueryStatus before any rows, follow NextToken until it is absent, and file the statement, query id, store id, and result count with the note.
Status before rows
start-query returns a query id and does not wait. get-query-results then reports QueryStatus. FINISHED means the engine completed and the statistics block is meaningful. FAILED, CANCELLED, and TIMED_OUT are outcomes with a message, not an empty story. QUEUED and RUNNING mean you do not have the answer yet.
Impact of reading too early: an empty row list while the status is still RUNNING looks like “nothing happened.” Control: write the status on the note, and only then write the rows. A failure message is copied too, so the next person does not rerun a broken statement and think the account was quiet.
aws cloudtrail get-query-results --query-id "$QID" \
--query '{Status:QueryStatus,Error:ErrorMessage,Stats:QueryStatistics,Token:NextToken}'The first page is not the set
QueryStatistics.ResultsCount is how many rows the finished query produced. The body holds one page. When NextToken is present, pass it back as --next-token and repeat until the token is absent. Counting the lines on the first screen undercounts whenever the token was set.
What not to trust: “only a handful of calls” when ResultsCount is larger than the page you pasted. The note records ResultsCount and how many pages you actually saved.
What to file with the rows
Save the statement text, the event data store id in the FROM clause, the query id, the final status, ResultsCount, and TotalBytesScanned when the statistics include it. Those fields are how someone else reruns the same question and notices if the store or the window changed. A screenshot of a table without the statement cannot be rerun.
store: <event data store id> queryId: <id> status: FINISHED resultsCount: <from QueryStatistics> pagesSaved: <how many NextToken steps you followed> bytesScanned: <from QueryStatistics> statement: | <the SQL, including the time bound>
Lab: force a second page in the sandbox
Point a query at a few hours of your own sandbox management events, with a time bound, and pass a small page size so a busy hour returns a token. Record status on the first call. If it is not FINISHED, wait and call again with the same query id. Then walk NextToken until it disappears, and check that the rows you saved add up to ResultsCount.
If the status is FAILED, the lab note is the error message and the statement, not a claim that the account had no events. Fix the statement in the sandbox and run a new query id. Do not reuse the failed id as if it were a finished result.
Diagram
From a query id to a complete note
- Status
Read QueryStatus before counting rows.
FINISHED, not RUNNING
- Count
Copy ResultsCount from the statistics.
not the length of one page
- Pages
Follow NextToken until it is absent.
get-query-results --next-token
- File
Keep the statement, store id, and query id.
so the question can be rerun
Check yourself
1. Rows are empty and QueryStatus is RUNNING. What is true?
2. ResultsCount is 40 and the first response has a NextToken. What do you have?
3. Which item lets someone else rerun the question?