Latest research, product updates and best practices on staying secure in the cloud | Permiso

Extending Cloud Console Cartographer With New Mappings

Written by Daniel Bohannon | Jun 4, 2024 5:45:57 PM

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.

Blog: https://permiso.io/blog/introducing-cloud-console-cartographer-an-open-source-tool-to-help-security-team-easily-understand-log-events-generated-by-aws-console-use

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:

                  1. In the SignalDefinitions.ps1 file add a new Signal 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 both Label and Signal references.

                     

                     

                     

                    Example Signal enum in SignalDefinitions.ps1 file

                     

                1. In the SignalDefinitions.ps1 file add a new Signal class constructor definition for the events and metadata associated with the CloudTrail_Insights enum created in Step #1. At a minimum this involves the event listings (AnchorEvents, RequiredEvents and OptionalEvents) along with the base metadata to be included in the generated Signal objects (including placeholder values like in the Url and Summary properties that can be substituted at the time of the Signal generation).

                   


                   

                  Example Signal class constructor in SignalDefinitions.ps1 file

                   

                   

                   

      1. In the AddLabels.ps1 file’s Add-Label function add the CloudTrail_Insights enum created in Step #1 to all events defined in the Signal definition in Step #2. If the eventSource + 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’s requestParameters and userAgent 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’s AnchorEvents property) determine the order of priority of potentially competing and overlapping Signals during the generation process.

         

         

        Example Label application for specific eventSource + eventName pairing in AddLabels.ps1 file’s Add-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:

      1. Input current events into the New-UnitTest function to automatically create minimized input event file and expected output result file in Tests/Sessions folder: dir ./demoEvents.json | New-UnitTest -Verbose


        Creation of unit test files for current events and Signals: dir ./demoEvents.json | New-UnitTest -Verbose




        1. 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!