Correlate AWS Federation Token Generation with Console Logins

Correlate AWS CloudTrail events (GetFederationToken action and ConsoleLogin action) by the same user within a 60-minute window using the correlate() function

Query

flowchart LR; %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% repo{{Events}} 1[/Filter/] 2["GetFederationToken: Table"] 3["ConsoleLogin: Table"] 4[(Function)] result{{Result Set}} repo --> 1 1 --> 2 1 --> 3 2 --> 4 3 --> 4 4 --> result
logscale
#Vendor="aws" #event.kind="event" #event.module="cloudtrail"
| correlate(
    GetFederationToken:{event.action="GetFederationToken"},
    ConsoleLogin:{event.action="ConsoleLogin" 
    | user.name <=> GetFederationToken.user.name},
sequence=true,within=60m)

Introduction

The correlate() function can be used to match and combine events from multiple queries based on specified field values within a defined time window. The set of returned events will consist of a list of events, identified by their correlation query name, and containing the matching connection fields from each event.

In this example, the correlate() function is used to match AWS GetFederationToken events with corresponding ConsoleLogin events for the same user within a 60-minute window, ensuring the events occur in sequence.

The correlate() function finds relationships between the events within the GetFederationToken and ConsoleLogin queries. sequence=true means that events in a constellation must occur in the order that the queries are defined within the time window

Example incoming data might look like this:

@timestamp#Vendor#event.kind#event.moduleevent.actionuser.namesource.ipaws.cloudtrail.event_id
2023-06-15T08:00:00ZawseventcloudtrailGetFederationTokenalice.smith10.0.1.100a1b2c3d4
2023-06-15T08:01:30ZawseventcloudtrailConsoleLoginalice.smith10.0.1.100e5f6g7h8
2023-06-15T09:15:00ZawseventcloudtrailGetFederationTokenbob.jones10.0.2.200i9j0k1l2
2023-06-15T10:25:00ZawseventcloudtrailConsoleLoginbob.jones10.0.2.200m3n4o5p6
2023-06-15T10:30:00ZawseventcloudtrailGetFederationTokencharlie.brown10.0.3.150q7r8s9t0
2023-06-15T11:45:00ZawseventcloudtrailConsoleLogincharlie.brown10.0.3.150u1v2w3x4
2023-06-15T11:00:00ZawseventcloudtrailGetFederationTokendave.wilson10.0.4.175y5z6a7b8
2023-06-15T12:15:00ZawseventcloudtrailConsoleLogindave.wilson10.0.4.175c9d0e1f2
2023-06-15T12:45:00ZawseventcloudtrailGetFederationTokeneve.parker10.0.5.225g3h4i5j6
2023-06-15T12:46:15ZawseventcloudtrailConsoleLogineve.parker10.0.5.225k7l8m9n0

Step-by-Step

  1. Starting with the source repository events.

  2. flowchart LR; %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% repo{{Events}} 1[/Filter/] 2["GetFederationToken: Table"] 3["ConsoleLogin: Table"] 4[(Function)] result{{Result Set}} repo --> 1 1 --> 2 1 --> 3 2 --> 4 3 --> 4 4 --> result style 1 fill:#ff0000,stroke-width:4px,stroke:#000;
    logscale
    #Vendor="aws" #event.kind="event" #event.module="cloudtrail"

    Filters for events from #Vendor=aws with #event.kind=event and #event.module=cloudtrail.

  3. flowchart LR; %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% repo{{Events}} 1[/Filter/] 2["GetFederationToken: Table"] 3["ConsoleLogin: Table"] 4[(Function)] result{{Result Set}} repo --> 1 1 --> 2 1 --> 3 2 --> 4 3 --> 4 4 --> result style 2 fill:#ff0000,stroke-width:4px,stroke:#000;
    logscale
    | correlate(
        GetFederationToken:{event.action="GetFederationToken"},

    Defines the first query named GetFederationToken to match AWS federation token generation events. Filters for events with event.action=GetFederationToken which captures all AWS Security Token Service (STS) federation token creation requests.

  4. flowchart LR; %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% repo{{Events}} 1[/Filter/] 2["GetFederationToken: Table"] 3["ConsoleLogin: Table"] 4[(Function)] result{{Result Set}} repo --> 1 1 --> 2 1 --> 3 2 --> 4 3 --> 4 4 --> result style 3 fill:#ff0000,stroke-width:4px,stroke:#000;
    logscale
    ConsoleLogin:{event.action="ConsoleLogin" 
        | user.name <=> GetFederationToken.user.name},

    Defines the second query named ConsoleLogin to match AWS console login attempts. Filters for events with event.action=ConsoleLogin which captures all AWS Management Console authentication events.

    The correlation relationship (condition) is specified using the <=> operator which requires exact matches between fields (field correlation matches).

    The user.name field from this ConsoleLogin event must match the user.name field from the GetFederationToken event. The corresponding fields will be used to join the events together across all the queries in the set. This ensures that events will only be correlated when they relate to the same user's authentication sequence, preventing false correlations between different users' token generations and logins.

  5. flowchart LR; %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% repo{{Events}} 1[/Filter/] 2["GetFederationToken: Table"] 3["ConsoleLogin: Table"] 4[(Function)] result{{Result Set}} repo --> 1 1 --> 2 1 --> 3 2 --> 4 3 --> 4 4 --> result style 4 fill:#ff0000,stroke-width:4px,stroke:#000;
    logscale
    sequence=true,within=60m)

    Sets correlation parameters:

    • sequence=true ensures that GetFederationToken events must occur before ConsoleLogin events.

    • within=60m specifies that the console login must occur within 60 minutes of token generation, matching the typical federation token validity period.

    By default, the query will match the event correlation only once per root query (return the first match), as the maxPerRoot parameter is not specified.

    The correlate() function outputs each pair of matched events as a single event containing fields from both sources, prefixed with their respective subquery names (for example, GetFederationToken.user.name, consoleLogin.@timestamp).

  6. Event Result set.

Summary and Results

The query is used to track the complete authentication flow for federated users accessing the AWS Console, ensuring proper sequence and timing of authentication events. The correlate() function tracks authentication sequences by matching federation token generation events with subsequent console login attempts within a specified time window.

This query is useful, for example, to monitor federation token usage patterns, detect potential token sharing or misuse, and verify that console logins occur within expected timeframes after token generation.

Sample output from the incoming example data:

@timestampGetFederationToken.user.nameGetFederationToken.source.ipGetFederationToken.aws.cloudtrail.event_idConsoleLogin.@timestampConsoleLogin.source.ipConsoleLogin.aws.cloudtrail.event_idTimeBetweenEvents
2023-06-15T08:00:00Zalice.smith10.0.1.100a1b2c3d42023-06-15T08:01:30Z10.0.1.100e5f6g7h890
2023-06-15T09:15:00Zbob.jones10.0.2.200i9j0k1l22023-06-15T10:25:00Z10.0.2.200m3n4o5p64200
2023-06-15T12:45:00Zeve.parker10.0.5.225g3h4i5j62023-06-15T12:46:15Z10.0.5.225k7l8m9n075

Note that the following events are excluded from the results because their ConsoleLogin occurred more than 60 minutes after the GetFederationToken:

  • charlie.brown's login at 11:45:00Z (75 minutes after token generation at 10:30:00Z)

  • dave.wilson's login at 12:15:00Z (75 minutes after token generation at 11:00:00Z)

This demonstrates how the within=60m parameter filters out login attempts that occur outside the expected federation token usage window.

Note that the output includes timestamps from each query. The TimeBetweenEvents field shows the seconds between token generation and console login, useful for identifying unusual login patterns.