DivvyCloud

Welcome to the DivvyCloud Docs!

DivvyCloud is a Cloud Security Posture Management (CSPM) platform that provides real-time analysis and automated remediation across leading cloud and container technologies.

For questions about documentation reach out to us [email protected]

Take Me to the Docs!    Release Notes

Jinja2 - References

Overview of Jinja2 References

On this page we will will walk you through the references that you will need within DivvyCloud when configuring your Jinja2 templates.

The main "references" include:

  • Resource Attributes and Resource Common Attributes
  • Resource Functions

This page also provides a variety of pre-built custom messages and two examples of advanced templating for policy.

Resource Attributes

Available attributes vary based on the resource type (e.g., instances). A list of available attributes based on the resource type can be found through each category page, as follows:

📘

Finding a Specific Resource

We suggest navigating to the appropriate category page (e.g. Compute, Storage, etc.) and locating the individual resource. These are listed in the contents for each page on the right and can be accessed via that in-page Table of Contents, or by using a basic search on the page (e.g. CMD + F).

Using Resource Attributes

When using these actions, access resource properties by using the following syntax:

{{resource.<attribute>}}

Resource Common Data

For certain resources, the attribute details must be expressed in a slightly different format. Within DivvyCloud there are a handful of resources that share what we refer to as "common data" and they are identified as such within our database.

To include these attributes you can access the properties of these specific resources with the following syntax:

{{resource.common.<attribute>}}

This syntax applies to ONLY the following:

"resource_id", 
"resource_name",
"resource_type",
"cloud",
"account",
"account_id",
"organization_service_id",
"availability_zone",
"region",
"creation_timestamp",
"discovered_timestamp",
"modified_timestamp",
"namespace_id"

Resource External Data

Accessing external data also requires a different format, as it directly references the external data parameters harvested by DivvyCloud.

To include these external data parameters for a given resource ID, use the following syntax:

{{resource.get_resource_id()}}
{{resource.ext.<parameter>}}

The <parameter> reference should be substituted with any of the named parameters found within a defined external data source. See Managing External Resources for more information.

Resource Functions

In addition to resource attributes DivvyCloud includes support for some resource functions. Since our platform supports hundreds of resources if you are interested in a resource function or configuration that you do not see listed here reach out to our team at [email protected].

When using these actions, you can access resource properties by using the following syntax:
{{resource.<function>}}

Each of the resource functions below (listed alphabetically) provides a high-level explanation of the capability and the associated template element(s).

Get Access Key Info

You can include this resource function in a Bot configuration for the Cloud User Resource Type. Doing so will retrieve information about the API access keys including the key ID, key status, create date, last used date, and age in days for any users included within the Bot scope.

{{resource.get_access_key_info()}}

For example:

{
   "access_key_id": "AKIA3ABCDEFGHIJLLMNOP",
   "status": "active",
   "create_date": "2019-10-29 20:31:40",            
   "last_used_date": "2019-11-20 22:05:00",
   "age_in_days": 266
 }

Get Age in Days

Allows you to retrieve information about the age of a resource in days and is applicable in any context where a date field is available. The create_date can be specified or will be assumed by default. Alternatively you can specify other dates fields, e.g. last_used_date, as a parameter.

Date fields are included in the attributes throughout our Resources documentation for each individual resource. For example, API Access Key details are here.

{{resource.get_age_in_days()}}

This template can also provide the number of days since a Cloud User's password has been used, as follows:

{{resource.get_age_in_days('password_last_used')}}

Get Badge Value by Key for Parent Cloud

This new function is specific to our Microsoft Teams Integration and enables users to include dynamic details based on a particular badge key. By defining a Badge for Teams, users are able to identify multiple channels to target for messaging using a single bot action. (Previously users would be required to create a single bot action for each Teams channel using an individual webhook).



{{resource.get_badge_value_by_key_for_parent_cloud()}}

For example, where ‘Teams’ is your badge key:

{{resource.get_badge_value_by_key_for_parent_cloud('Teams')}}

Get Bot Name, Link, Severity, Description

Bot Name - {{event.bot_name}}
Bot ID - {{event.bot_id}}
Bot Link - {{event.direct_link}}
Bot Severity - {{event.bot_severity}}
Bot Description - {{event.bot_description}}
Bot Timestamp - {{event.timestamp}}

An example of this notification is:

Jinja2 Bot Notification Example

Get Date & Get Timestamp

We also support today() and utcnow(). Both can be used via event.get_date() and event.get_timestamp() Jinja2 functions respectively.

These functions, in combination with a tagging strategy, can be used to provide context such as indicating when a resource was tagged with time-relevant keys, e.g., "Owner notified of impending delete", "30 day exemption granted", etc.

In addition, the Filters Resource Tag Date Comparison and Resource Tag Date/Time Comparison, allow you to inspect those tags and make decisions based upon them, e.g., sending notifications, shutting down instances, deleting roles, etc.

Get Daily Cost

Calculate the daily cost for the resource in question. If the resource does not support cost calculation then this function will return None.

{{resource.get_daily_cost()}}

In addition, use the function below to round up and limit cost value to 2 decimal places.
For example:

  • Cost with limiting 2 decimals: $2.23
  • Cost without limiting decimals: $2.2272

{{"{0:.2F}". format(resource.get_daily_cost())}}

Get Impacted Resources

Include an optional tag key in the get_impacted_resources() to enrich the response with the value of the supplied tag. This enhancement applies to the following resource types:

  • AWS Trusted Advisor
  • AWS GuardDuty

Get Insight Name and ID

Insight Name - {{event.insight_name}}
Insight ID - {{event.insight_id}}

These fields can be used when a Bot is linked to an Insight. For example, a Bot flagging a resource can share the {{event.insight_name}} field to identify the specific Insight a resource is failing and to help the user more easily remedy the issue or add an exemption.

Get Last Event

This is a function that allows Bot authors to gain access to properties of the last event (from EDH) to further enrich Bot notification alerts. The syntax examples below allow you to obtain details from the last event object as follows:

  • User - {{resource.get_last_event().get('user')}}
  • User ARN - {{resource.get_last_event().get('user_arn')}}
  • Action - {{resource.get_last_event().get('action')}}
  • Timestamp - {{resource.get_last_event().get('timestamp')}}
  • IP - {{resource.get_last_event().get('ip')}}
  • Event ID - {{resource.get_last_event().get('event_id')}}
  • Event Tags - {{resource.get_last_event('tags')}}
  • Event Created - {{resource.get_last_event('create')}}
  • Event Modify - {{resource.get_last_event('modify')}}

Get Monthly Cost

Calculate the monthly cost for the resource in question. If the resource does not support cost calculation then this function will return None.

{{resource.get_monthly_cost()}}

In addition, use the function below to round up and limit cost value to 2 decimal places.
For example:

  • Cost with limiting 2 decimals: $2.23
  • Cost without limiting decimals: $2.2272

{{"{0:.2F}". format(resource.get_monthly_cost())}}

Get Organization Service Name and Account ID

These walk the resource to the parent organization service (cloud account) to retrieve the name and account number assigned to the account (e.g., Acmecorp AWS Production and 123456789012).

{{resource.get_organization_service_name()}}

{{resource.get_organization_service().account_id}}

Get Owner Name

In DivvyCloud you can assign ownership to resources. Doing this grants the owner full permission to that resource, and designates a point of contact (POC) for questions about the resource. This function will return the name of the POC if one is assigned, and None if one is not.

{{resource.get_owner_name()}}

Get Provider Link


Capture the provider link to create a notification (for Slack or other services) and share a direct link for the applicable resource in the provider console. (Currently only available for specific AWS resources, contact us via [email protected] with questions.)



{{resource.get_provider_link()}}.

An example of this notification type is:

Get Provider Link Output Example

Get Resource Age

This field {{resource.get_age_in_days()}} allows you to retrieve the age of a resource. Including resource age information can provide meaningful context and allow users to generate notifications or take actions based upon a resource's age, e.g., rotating API keys once their age exceeds a user-defined threshold.

Get Resource Name

This walks the resource to the database object and returns the name. For resources which do not have a name, the primary key value is returned. With public IP addresses, for example, the resource’s IP address will be returned.

{{resource.get_resource_name()}}

  • Note - this also works well with Bot actions that update S3 bucket policies, which require unique IDs, by using the bucket name, which is unique by definition. S3 bucket bot actions include object encryption and IP lockdown.

Get Tags from Cloud User via API Access Keys

You can include this resource function in a Bot configuration for the API Access Key Resource Type. Doing so will retrieve tag value(s) from the Cloud User using the API Access Key.

Input the tag key you're trying to retrieve the value for by replacing the "key_here" field, as shown in the example below:

{{resource.user.get_resource().get_tag_value(tag_key="key_here", case_insensitive=True)}}

Note: This function will only work with Users and is not applicable to any parent resource.

Get Tag Value

Get the value of a particular tag key. Only the tag key is required; however, you can optionally set the case_insensitive and default_return_str kwargs to force case sensitivity and/or return a specific value if the tag key does not exist.

{{resource.get_tag_value("tag_key", case_insensitive=True, default_return_str="None")}}

Get Users

Currently only applicable to Secure File Transfer.

Provides information pertaining to users authorized to SSH into target server, to include user_name, public_keys, key_id, date_imported, and home_directory_type for each authorized user on the server.

{{resource.get_users()}}

Example Custom Messages

Included below are several examples of dynamic messages that can be used in emails, Slack, and other messaging tools.

The title provides an explanation of their use case and includes the appropriate resource attributes and formatting. They can be copied and applied to any Bot you'd like to create.

To copy the message simply hover over the text to trigger the "copy" function and apply the pre-constructed template to your Bot.

Instance in Unapproved Region

An instance has been created in the unapproved region:`{{resource.region_name}}`
Instance Name: `{{resource.name}}`
Instance ID: `{{resource.instance_id}}`
Instance Launch Time: `{{resource.launch_time}}`

Instance Details:
{{resource.serialize(indent=2)}}

Ensure Tag Strategy is Enforced

A resource of type {{resource.get_resource_type()}} was discovered at
{{resource.common.creation_timestamp}} without the required *owner*
or *contact-email* tags. The resource name is `{{resource.get_resource_name()}}`.
It lives in account `{{resource.get_organization_service_name()}}`.

Instance Has More Than 4 Cores

`{{resource.name}}` has been created or discovered with more than 4 cores. 
This resource will cost `${{resource.get_daily_cost()}}`/day. 
The details are `{{resource.serialize(indent=2)}}`. 
If this instance isn't downsized or cleaned up, 
it will be deleted within 6 hours.

A Resource You Own Was Removed

The resource `{{resource.name}}` which belongs to you, has been deleted. 
Details below: `{{resource.serialize(indent=2)}}`

Instance With Public IP Has SSH Open To The World

Instance `{{resource.instance_id}}` is `{{resource.state}}` and has a
public IP address of `{{resource.public_ip_address}}`. This instance has exposed
port 22 (SSH) open to the world. This instance is not within our security policy. Please
lock down the attached ACLs `{{resource.access_lists}}`, or this instance will be
deleted in 4 hours.

Bad ACL

Bad ACL found on `{{resource.name}}`. Please login to investigate!

Expensive Instance was created or discovered

A very expensive instance `{{resource.get_resource_name()}}` created at
`{{resource.common.creation_timestamp}}` was found in account
`{{resource. get_organization_service_name()}}` which costs
`${{resource.get_daily_cost()}}/day` and `${{resource.get_monthly_cost()}}/mo`.

Database Open to the World

An insecure database was identified with access open to the World.
The details of this resource are:
`{{resource.serialize(indent=2)}}`.

Storage Container Public Access

An insecure storage container was identified with public permissions to the world.
The details of this resource are:
`{{resource.serialize(indent=2)}}`.
The resource has the following tags
`{{resource.serialize_tags(indent=2)}}`
This storage container is scheduled for deletion in 24 hours.
Please update security access rules to avoid the scheduled deletion.

CloudWatch Alarm has triggered

A CloudWatch Alarm has triggered. The data on the alarm is:
ID of the parent organization service (cloud): `{{resource.organization_service_id}}`
ID of alarm: `{{resource. alarm_id}}`
Name of Alarm: `{{resource.name}}`
ARN for the account where this alarm resides: `{{resource.common.provider_id}}`
An optional, brief description of this alarm: `{{resource.description}}`
Namespace (container for CloudWatch metrics) of the alarm: `{{resource.namespace}}`
Name of the metric this alarm checks for: `{{resource.metric_name}}`
User defined threshold for this alarm: `{{resource.threshold}}`
Amount of times this data will be evaluated before arriving at conclusion for alarm: `{{resource.evaluation_periods}}`
Alarm Type: `{{resource.state_value}}`
Alarm Reason: `{{resource.state_reason}}`
More data regarding this alarm: `{{resource.state_reason_data}}`

Database Instance has had Zero Connections in 14 days

Database instance `{{resource.name}}` has had no connections within 14 days. This database instance
resides in `{{resource.get_organization_service_name()}}` account and has an endpoint of
`{{resource.endpoint_address}}`.
This resource will have a snapshot taken, will be stopped, and finally deleted after 7 days.

Instance Provisioned outside of AMI Whitelist

'{{resource.image_id}}' has been used to provision instance `{{resource.instance_id}}`
in `{{resource.organization_service_name}}`. This machine image is not permitted.
This instance will have a snapshot taken, and be terminated immediately.

User without MFA Enabled

`{{resource.get_resource_type()}}: {{resource.get_resource_name()}}` in account `{{resource. get_organization_service_name()}}` with account # `{{resource.get_organization_service().account_id}}` does not have MFA enabled.

Custom Policies (Advanced)

In addition to templating for various notifications DivvyCloud also supports the use of Jinja2 templating to add or update S3 bucket policies. These advanced capabilities are included here as examples/references of these capabilities. If you're interested in implementing Jinja2 in a more advanced way using custom policies we recommend connecting with our team through [email protected]

In our two examples of updating bucket policy the first demonstrates the Jinja2 template required to enforce encryption, and the second is to restrict access.

Bucket Encryption Policy

If you would like to enforce encryption via bucket policy, you can create a bot that uses the "Set Container Policy" action and the following template to enforce encryption.

{
    "Version": "2012-10-17",
    "Id": "bucketpolicyid:{{event.resource.get_resource_name()}}",
    "Statement": [
        {
            "Sid": "DenyIncorrectEncryptionHeader",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::{{event.resource.get_resource_name()}}/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": "AES256"
                }
            }
        },
        {
            "Sid": "DenyUnEncryptedObjectUploads",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::{{event.resource.get_resource_name()}}/*",
            "Condition": {
                "Null": {
                    "s3:x-amz-server-side-encryption": "true"
                }
            }
        }
    ]
}

Bucket Lockdown Policy

If you would like to restrict bucket access to certain IP ranges or block specific IP ranges, you can use "Set Container Policy" and the following template to "lock down" the bucket to those IP ranges.

{
    "Version": "2012-10-17",
    "Id": "bucketpolicyid:{{event.resource.get_resource_name()}}",
    "Statement": [
        {
            "Sid": "IPAllow",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::{{event.resource.get_resource_name()}}/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "<insert IP range to block>"
                },
                "IpAddress": {
                    "aws:SourceIp": "<or insert IP range to allow>"
                }
            }
        }
    ]
}

Updated about a month ago


Jinja2 - References


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.