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.ps1
file add a newSignal
enum 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 bothLabel
andSignal
references.Example
Signal
enum inSignalDefinitions.ps1
file
-
-
In the
SignalDefinitions.ps1
file add a newSignal
class constructor definition for the events and metadata associated with theCloudTrail_Insights
enum created in Step #1. At a minimum this involves the event listings (AnchorEvents
,RequiredEvents
andOptionalEvents
) along with the base metadata to be included in the generated Signal objects (including placeholder values likein the
Url
andSummary
properties that can be substituted at the time of the Signal generation).Example
Signal
class constructor inSignalDefinitions.ps1
file
-
-
-
-
-
-
In the
AddLabels.ps1
file’sAdd-Label
function add theCloudTrail_Insights
enum created in Step #1 to all events defined in the Signal definition in Step #2. If theeventSource
+eventName
pairing 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’srequestParameters
anduserAgent
properties. 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’sAnchorEvents
property) determine the order of priority of potentially competing and overlapping Signals during the generation process.Example Label application for specific
eventSource
+eventName
pairing inAddLabels.ps1
file’sAdd-Label
function
-
-
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-UnitTest
function to automatically create minimized input event file and expected output result file inTests/Sessions
folder: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/Sessions
folder 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!