Extending Cloud Console Cartographer With New Mappings
Hear Ye, Hear Ye
Subscribe to Cloud Chronicles for the latest in cloud security!
Last month Permiso’s P0 Labs released the Cloud Console Cartographer open-source framework and corresponding research presentation at Black Hat Asia in Singapore. Recently we released our full suite of unit tests. Now let’s talk about how to extend the framework by adding new mapping definitions.
By way of background, Cloud Console Cartographer is a framework for condensing groupings of cloud events (e.g. CloudTrail logs) and mapping them to the original user input actions in the management console UI for simplified analysis and explainability. This is extremely beneficial for defenders since numerous input actions in management console sessions can generate 10's and even many 100's of events originating from a single interactive click by the end user.
Source Code: https://github.com/Permiso-io-tools/CloudConsoleCartographer
We recently added our full unit tests to the project to make it easier for the community to contribute new mappings while quickly ensuring any updates do not break existing mappings. There are many complex scenarios to account for since mappings are based on event combinations that can often be overlapping from a timeline perspective. Therefore, unit tests calculated for entire sessions of events is the most effective format that we use for all internal and external unit tests for this framework.
In this blog post we will outline the steps required to create a new mapping in Cloud Console Cartographer. We will focus on the components required for an existing mapping to highlight the order and interworking between Signal definitions, Label applications and then the remaining Signal generation and optional Signal modifications.
Generation of CloudTrail Events for Mapping
First we will create an AWS Management Console session and perform the manual click-mapping of the service, in this case the CloudTrail service. After clicking on CloudTrail→Insights we will record the exact time of the click so we can retrieve the CloudTrail events corresponding to the activity.

Screenshot of AWS Management Console: CloudTrail->Insights
Focusing on the first click, CloudTrail->Insights, we can see the following events and corresponding requestParameters and userAgent values were generated:

CloudTrail events generated when clicking CloudTrail->Insights
Creating New Mapping (via Signal and Label Definitions)
Translating a simple mapping like this in Cloud Console Cartographer is as simple as 1-2-3 in the following files in the Code directory of the project:
-
-
-
-
-
-
-
-
-
In the
SignalDefinitions.ps1file add a newSignalenum corresponding to the breadcrumb of where the click can be found in the AWS Managment Console:CloudTrail_Insights. This enum will be used throughout the rest of the code as bothLabelandSignalreferences.
Example
Signalenum inSignalDefinitions.ps1file
-
-
In the
SignalDefinitions.ps1file add a newSignalclass constructor definition for the events and metadata associated with theCloudTrail_Insightsenum created in Step #1. At a minimum this involves the event listings (AnchorEvents,RequiredEventsandOptionalEvents) along with the base metadata to be included in the generated Signal objects (including placeholder values likein theUrlandSummaryproperties that can be substituted at the time of the Signal generation).
Example
Signalclass constructor inSignalDefinitions.ps1file
-
-
-
-
-
-
In the
AddLabels.ps1file’sAdd-Labelfunction add theCloudTrail_Insightsenum created in Step #1 to all events defined in the Signal definition in Step #2. If theeventSource+eventNamepairing is not yet listed in this file’s switch statement then add the appropriate switch statement structure to successfully match the event. This is where particular focus should be directed to the event’srequestParametersanduserAgentproperties. Whichever switch statement block is matched (if any) then all the listed Labels will be returned in the order they are listed. This ordering is extremely important in the Signal generation process as it (paired with strategic specification in each Signal definition’sAnchorEventsproperty) determine the order of priority of potentially competing and overlapping Signals during the generation process.
Example Label application for specific
eventSource+eventNamepairing inAddLabels.ps1file’sAdd-Labelfunction
-
-
That’s it! Nothing else is required to add a new mapping for this simple scenario. Re-running the framework will now group these labeled events and cause the corresponding Signal to be generated.
Simple substitutions like placeholder value in each Signal definition’s Url and Summary properties are automatically performed for all generated Signals. Any additional optional substitutions and multi-event information extraction steps occur in NewSignal.ps1 file’s New-Signal function (shown below). More nuanced Signal overrides, merges and look-ahead/look-behind Signal-borrowing scenarios are defined in AddSignal.ps1 file’s Add-Signal function (not shown).

Example Signal Summary and Url modifications in NewSignal.ps1 file’s New-Signal function.
Debugging Mappings
A helpful function for debugging at the event level is Show-EventSummary -Detail signal,event_mapped,event_unmapped which displays every event (green if mapped to a Signal, yellow if not) with additional Signal details above and event metadata below that is useful for updating Label assignment logic in AddLabels.ps1 file’s Add-Label function. Of note is the list of Labels evaluated for each event (same list of Labels added in Add-Label function for each event in specific matching switch statement) with color-coding to show which Labels did not contribute to a Signal (red), did contribute to a Signal (green) or were skipped due to previous successful Signal contribution (grey).

Debugging command: dir ./demoEvents.json | Add-Signal | Show-EventSummary -Detail signal,event_mapped,event_unmapped
Unit Tests
The last step after confirming the new Signal is working as expected on our generated session data is to ensure we did not break or clobber any other Signal logic. This is where the latest update of the unit tests tooling in the Tests folder comes into play.
We tried to make unit testing as simple as 1-2:
-
-
-
Input current events into the
New-UnitTestfunction to automatically create minimized input event file and expected output result file inTests/Sessionsfolder:dir ./demoEvents.json | New-UnitTest -Verbose
Creation of unit test files for current events and Signals:
dir ./demoEvents.json | New-UnitTest -Verbose
-
Run unit tests for specific test sessions (organized by dynamically generated session ID) or all sessions in
Tests/Sessionsfolder using the Pester unit testing framework:Invoke-Pester -TagFilter FullEvent
E
xecution of all unit tests:
Invoke-Pester -TagFilter FullEvent
-
-
-
Conclusion
While this blog post does not seek to exposit all the intricate capabilities of the Cloud Console Cartographer framework meant to handle numerous complicated clobbering scenarios, Signal merge scenarios or look-ahead/look-behind Signal-borrowing scenarios, we hope it is enough to get interested community members started in codifying their own knowledge of AWS Management Console click-mappings into a repeatable and shareable framework.
Stay tuned for more project updates plus new research and open-source tools from the Permiso P0 Labs team!


