Query Details

AWS Cloud Trail AWS Account Created

Query

let _AWSAccounts =
    _GetWatchlist("AccountId-AuditAWSAccounts")
    | project RecipientAccountId = AccountId, RecipientAccountName = AccountName
;
union
    (
    AWSCloudTrail
    | where EventName in ("ProvisionProduct", "UpdateProvisionedProduct")
    | extend
        DynamicResponseElements = todynamic(ResponseElements),
        DynamicRequestParameters = todynamic(RequestParameters)
    | where tostring(DynamicResponseElements["recordDetail"]["provisionedProductType"]) has "ACCOUNT"
    | mv-apply ProvisioningParameter = DynamicRequestParameters["provisioningParameters"] on (
        summarize ProvisioningParameters = make_bag(bag_pack(tostring(ProvisioningParameter["key"]), ProvisioningParameter["value"]))
        )
    | extend
        Status = tostring(DynamicResponseElements["recordDetail"]["status"]),
        ProvisionedProductId = tostring(DynamicResponseElements["recordDetail"]["provisionedProductId"]),
        AccountName = tostring(ProvisioningParameters["AccountName"]),
        ManagedOrganizationalUnit = tostring(split(tostring(ProvisioningParameters["ManagedOrganizationalUnit"]), " ")[0]),
        AccountEmail = tostring(ProvisioningParameters["AccountEmail"]),
        SSOUserEmail = tostring(ProvisioningParameters["SSOUserEmail"])
    ),
    (
    AWSCloudTrail
    | where EventTypeName == "AwsApiCall" and EventName in ("CreateManagedAccount")//, "UpdateManagedAccount")
    | extend DynamicRequestParameters = todynamic(RequestParameters)
    | extend
        ProvisionedProductId = tostring(DynamicRequestParameters["provisionedProductId"]),
        AccountName = tostring(DynamicRequestParameters["accountName"]),
        ManagedOrganizationalUnit = tostring(split(tostring(DynamicRequestParameters["parentOrganizationalUnitName"]), " ")[0]),
        AccountId = tostring(DynamicRequestParameters["accountId"])
    )
| summarize
    StartTime = min(TimeGenerated),
    EndTime = max(TimeGenerated),
    take_any(UserIdentityType),
    //take_any(UserIdentityPrincipalid),
    take_any(UserIdentityArn),
    take_any(UserIdentityAccountId),
    take_any(UserIdentityUserName),
    take_any(SessionIssuerAccountId),
    take_any(SessionIssuerUserName),
    SourceIPAddresses = array_sort_asc(make_set_if(SourceIpAddress, not(SourceIpAddress has_any (".amazonaws.com", "AWS Internal")))),
    EventSource = array_sort_asc(make_set(EventSource)),
    EventName = array_sort_asc(make_set(EventName)),
    take_any(AWSRegion),
    take_any(Status),
    arg_max(TimeGenerated, ManagedOrganizationalUnit),
    take_any(AccountId),
    take_any(ProvisionedProductId),
    UserAgent = array_sort_asc(make_set_if(UserAgent, not(SourceIpAddress has_any (".amazonaws.com", "AWS Internal"))))
    by UserIdentityPrincipalid, RecipientAccountId, AccountName
| where EventName has "ProvisionProduct"
| lookup kind=leftouter (
    AWSCloudTrail
    | where EventName in ("CreateManagedAccount", "UpdateManagedAccount") and EventTypeName == "AwsServiceEvent"
    | extend DynamicServiceEventDetails = todynamic(ServiceEventDetails)
    | extend ServiceEventDetailsKey = tostring(bag_keys(DynamicServiceEventDetails)[0])
    | project
        TimeGenerated,
        ServiceEventDetails,
        AccountName = tostring(DynamicServiceEventDetails[ServiceEventDetailsKey]["account"]["accountName"]),
        ManagedOrganizationalUnit = tostring(DynamicServiceEventDetails[ServiceEventDetailsKey]["organizationalUnit"]["organizationalUnitName"]),
        AccountId = tostring(DynamicServiceEventDetails[ServiceEventDetailsKey]["account"]["accountId"])
    | summarize arg_max(TimeGenerated, *) by AccountName, AccountId
    | project-away TimeGenerated
    ) on AccountName
| extend AccountId = coalesce(AccountId1, AccountId)
| lookup kind=leftouter _AWSAccounts on RecipientAccountId
| project
    StartTime,
    EndTime,
    RecipientAccountId,
    RecipientAccountName,
    UserIdentityType,
    UserIdentityPrincipalid,
    UserIdentityArn,
    UserIdentityAccountId,
    UserIdentityUserName,
    SessionIssuerAccountId,
    SessionIssuerUserName,
    SourceIPAddresses,
    EventSource,
    EventName,
    Status,
    ManagedOrganizationalUnit,
    AccountName,
    AccountId,
    ProvisionedProductId,
    AWSRegion,
    ServiceEventDetails,
    UserAgent

Explanation

The query retrieves information about AWS accounts and their provisioning activities. It combines data from two sources, AWSCloudTrail and a watchlist called "AccountId-AuditAWSAccounts".

The query filters events related to provisioning products and updates, as well as events related to creating and updating managed accounts. It extracts relevant information such as account name, provisioning parameters, status, provisioned product ID, managed organizational unit, account email, and SSO user email.

The query then summarizes the data by various fields such as start time, end time, user identity, source IP addresses, event source, event name, status, managed organizational unit, account ID, provisioned product ID, AWS region, service event details, and user agent. It also performs lookups to enrich the data with additional information from the watchlist.

The final result includes the summarized information for each account, including the start and end times of the provisioning activities, recipient account ID and name, user identity details, source IP addresses, event details, status, managed organizational unit, account name, account ID, provisioned product ID, AWS region, service event details, and user agent.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: August 4, 2023

Tables

AWSCloudTrail

Keywords

Devices,Intune,User

Operators

projectunionwhereextendmv-applysummarizesplittostringmake_bagbag_packtake_anyarray_sort_ascmake_set_ifnothas_anybylookupcoalesceproject-away

Actions