CloudFormation mapping
This mapping configuration only applies to CloudFormation Processor.
Please refer to another mapping file configuration documentation if needed. You can locate each processor's documentation in the left menu under the "StartLeft Processors (SLP)" section.
A source mapping file (or "mapping files" for short) describes how to find components, dataflows, and trustzones in source file data structures.
To accomplish this, a mapping file contains additional logic around a collection of JMESPath queries which are used. Also, some exclusive StartLeft actions based on JMESPath may be used in mapping files to solve the most complex mappings.
Source mapping files are made up of three main sections corresponding to the main sections in an OTM file, plus an optional lookup section described below:
- trustzones
- components
- dataflows
Each contains a list of 0 or more objects that describe how to find the respective object in the source file, and each object has a number of required and optional fields.
Take a look at the JSONSchema file for more details.
JMESPath Queries
Special $action fields begin with a dollar sign ($) and do not directly contribute to the OTM output. Instead, they specify an action and behaviour used to process the source files or generate the OTM output.
This table describes each special $actions:
$action | Description | Example |
---|---|---|
$source | Specifies the source of the object type | $source: |
$root | JMESPath search through the entire source file data structure | $root: "Resources|squash(@)[?Type=='AWS::EC2::VPC']" |
$path | JMESPath search through the object identified in the $source. A default value is optional by using the $searchParams structure | $path: "Type" $path: "Properties.VpcId.Ref" $path: {$searchParams:{ searchPath: "Properties.SubnetId.Ref", defaultValue: "b61d6911-338d-46a8-9f39-8dcd24abfe91"}} |
$findFirst | JMESPath search through the list of objects identified in the $source and returning the first successful match. A default value is optional by using the $searchParams structure | $findFirst: ["Properties.FunctionName.Ref", "Properties.FunctionName"] $findFirst: {$searchParams:{ searchPath: ["Properties.SubnetId.Ref","Properties.SubnetId"], defaultValue: "b61d6911-338d-46a8-9f39-8dcd24abfe91"}} |
$format | A named format string based on the output of other $special fields. Note, only to be used for id fields. | $format: "{name}" |
$catchall | A sub-field of $source, specifying a default search for all other objects not explicitly defined | $catchall: |
$skip | A sub-field of $source, specifying specific objects to skip if not explicitly defined | $skip: |
$singleton | A sub-field of $source, specifying specific objects to be unified under a single component or trustzone | $singleton: |
$numberOfSources | When using singleton, allows you to set different values for output name or tags when the number of sources for the same mapping are single or multiple | $numberOfSources: {oneSource:{$path: "_key"}, multipleSource:{ $format: "CD-ACM (grouped)" }} |
$altsource | Specifies an alternative mapping when $source returns no object. | $altsource: - $mappingType: {$root: "Resources|squash(@)[?Type=='AWS::EC2::VPCEndpoint']"} $mappingPath: {$path: "Properties.ServiceName"} $mappingLookups: - regex: ^(.*)s3$ name: S3 from VPCEndpoint type: s3 |
$lookup | Allows you to look up the output of a $special field against a key-value lookup table | $lookup: |
$hub | Only for dataflow's "source" and "destination" fields. Especially created for building dataflows from Security Group structures without generating components from them. Allows to define abstract contact points for larger end-to-end final dataflows | destination: {$hub: {$path: "Properties.GroupId"}} |
$ip | When defining a component's "name" field as $ip, will generate a singleton component for representing an external IP but without limitations of singleton for this case, so the "type" for the defined mapping definition with $ip (i.e. generic-terminal) will not be catalogued as singleton. | name: { $ip: { $path: "Properties.SecurityGroupEgress[0].CidrIp" } } |
For more information on how to create a JMESPath search query, check out the website.
Hardcoded values
In addition to using $source and other special $actions, you can also just hardcode values which will be taken and mapped as is. For example, you may want to specify a default trustzone which wouldn't be found anywhere in the source files. You can do this easily just by adding it to a mapping file:
Theid
field uniquely identifies a trustzone, and differentiates it from other trustzones of the same type.
For mapping trustzones to IriusRisk trustzones, type
field must take internal IriusRisk values depending on the type of trustzone.
These values are defined in the internal CloudFormation mapping file.
For the purpose of preserving backwards compatibility, StartLeft also accepts the legacy mapping file format. In this format, there is no
type
field and theid
will be used as both, ID and type.It is not possible to have multiple trustzones of the same type when using this format.
Lookup table
Just in case there are some inconsistencies in naming conventions used, and you need to be able to translate one name into another, a simple lookup key-value table section can be added to the mapping file.
For example, if we have a situation where a subnet name is written using a short naming convention, but is actually referred to via a longer name elsewhere, we can use the $lookup action.
parent:
$lookup: {$path: "Properties.Subnets[]|map(&values(@), @)[]|map(&re_sub('[:]', '-', @), @)"}
If the above query returns a subnet called shortnameA
, then it will be looked up in the below table:
To give a final value of amuchlongernameA
.
Additional JMESPath functions
Parsing of IaC files may be sometimes complex, so that the built-in JMESPath described above are not enough. For those cases, a set of custom functions has been created to simplify and make more powerful the creation of mapping files.
re_sub
The re_sub
function replaces the occurrences of pattern
with replace
in the given string
.
For example, we may want to replace colon characters with hyphens such as in re_sub('[:]', '-', 'stack:subnet')
.
squash
The squash
function takes a nested object of objects, and squashes them into a list of objects, injecting the parent "key" to the child object as "_key".
This function is specially useful for Cloudformation mapping files. These have a root Resources
object whose
top level keys are the resource names which have the resource objects as values. This structure is hard to iterate over
without losing the important name key. So you can use squash and refer to the name through the _key
field.
tail
The tail
function returns the characters of a given string
from the count
index onwards. It is equivalent to
python's string[count:]
.
get_starts_with
This function is equivalent to get
, but instead of using the component_type
argument to perform an exact filter, the
target component type must start with it.
split
The split
function is the equivalent to the python's one. It breaks a given string based on a given separator and
returns the resulting array of strings. It is equivalent to python's split
function.