Skip to main content

Actions

Actions allow you to define custom self-serve actions, including customizable input fields, that can send payloads from Cortex to any API (internal, external, or webhook). Actions can be tied to entities, or can be standalone. Some example actions you can build are:

  • Deploy action that asks the user for target environment and announcement channel, and triggers a build on GitHub for the service
  • Bug file action that creates a correctly formatted Jira ticket in the right project
  • One-click temporary access token provisioning for devs
  • Automatic AWS resource provisioning

Configurations

Admins can create and edit Actions. For the HTTP request, you'll be able to configure the:

  • HTTP method
  • URL (with templating)
  • Headers (this can store secrets/credentials, as we encrypt this header configuration at rest)
  • Default Payload (can be templated)
  • Response Template

Inputs

You're also able to define an optional list of inputs for the Action that the user will see when executing it.

Inputs can be text inputs, dropdowns, or toggles. You can configure the default value, placeholder, required/optional, and (for text inputs) regex validation.

Filtering

Actions can either be standalone, or connected to entities. If connected to an entity, the action will be executable from the catalog pages for those entities.

For entity-connected actions, you can apply filters to limit which entities the action will show up for.

Permissions

You're also able to configure the access control for who can trigger the action. Regardless of execution permissions, only admins are able to edit the Action configuration, view global execution history, and view decrypted header contents.

Templating

One of the most powerful features of Cortex Actions is their ability to be fully templated.

You can use Mustache templating to access the inputs provided by the user: {{context.inputs.KEY_NAME}}

You can also access your configured secrets by tag: {{context.secrets.SECRET_TAG}}. Note that Mustache performs HTML escaping by default, so if your configured secret contains a reserved HTML character, use triple braces to use raw content: {{{context.secrets.SECRET_TAG}}}.

If the Action is being run in the context of a catalog entity, the template context will also contain data about the entity.

  • tag
  • name
  • descriptor (this is the cortex.yaml, as an object)

These can be accessed under the {{context.entity}} key, for example {{context.entity.tag}} or {{context.entity.descriptor.info.x-cortex-git.github.repository}}

The context object also has the following keys:

  • {{context.initiatedAtIso8601Timestamp}}: The timestamp at which this action was initiated
  • {{context.initiatedBy}}: The user object of the initiator
    • email: The user's email

All of this templating is available for the URL and Payload fields of the Action configuration.

Example Payload:

{
"ref": "{{context.inputs.ref}}",
"auto_merge": "{{context.inputs.merge}}"
}

Under the hood, we use the Java mustache library.

Response template

The response template can reference the body of the response that is returned. The response can be accessed under the {{content.response.body}} key.

One use of the response body would be to contruct different responses if the Action is successful or not. For example, if you created an Action that used the Cortex API to update custom data, a successful response would include an attribute named id that could be accessed at {{context.response.body.id}}. Please note that a body in the response is not guaranteed, depending on the endpoint and HTTP status.

Using the Mustache concept of Inverted Sections, you could create different responses in your response template like this:

{{#context.response.body.id}}
Successfully updated custom data.
{{/context.response.body.id}}

{{^context.response.body.id}}
Unable to update custom data.
{{/context.response.body.id}}

Execution

Once you have configured an action, you can run it directly from the Action page, or from the Actions tab in the entity page if it's an entity-connected Action.

Based on your configuration, you'd be asked to

  • Select a Catalog Entity if applicable
  • Input all the required fields

At this point, just hit the Run Action button and Cortex will templatize & populate your payload and send the request to the defined URL. You'll be able to see the result directly in the execution modal.

caution

We have a 30 second time out for all Actions.

Execution History

For auditing and debugging purposes, we store the history of all previous Action runs, who ran them, and their HTTP request/responses. You'll be able to see your execution history in the Actions list or the history for a specific Action in the Action page.

Security

Security is a core principle at Cortex and we provide strong security guarantees for Actions.

Everything is encrypted in transit. Headers in the Action configuration, as well as final request/responses post-execution, are encrypted at rest and only visible to admins.

Request signing

If you're using Actions as a way to trigger hooks into internal tooling, we recommend validating that the request is actually originating from Cortex using request signing.

To get started, you'll need to configure a Signing Secret under Settings → Secrets in the Request Signing Secret section.

We add the following headers to each request made by Cortex:

  • x-cortex-timestamp (current timestamp in millis, used to prevent replay attacks)
  • x-cortex-signature
  • x-cortex-signature-256

These headers can be used to verify that the request is valid and originated from Cortex.

Note

x-cortex-signature contains the SHA1 hash of the request and exists for backward compatibility. SHA1 has been cracked and this signature should be considered deprecated. It is highly recommended to use x-cortex-signature-256, which contains the SHA256 hash.

To calculate the signature:

1. Create a string with the value "$timestamp.$requestBody" if the request body is non-null OR "$timestamp" if the request body is null. 
2. Calculate the SHA256 hash of this string using the Secret you provided to Cortex.
3. Verify that the x-cortex-signature-256 matches sha256=$calculatedSha256