Comprehensive Guide to TOML Graph Configuration

1. Overview

This document provides an in-depth technical reference for the TOML-based configuration system used to create a resource graph for a hybrid cloud. The system uses templating engine, where TOML files define how asset data is transformed into a rich, interconnected resource graph that captures interdependencies and automatically applies compliance controls.

There are two primary types of TOML configuration files:

  1. Architectural Models (data/models/*.toml): These files define the blueprint of the environment. They instruct the importer on how to create new types of resources (e.g., a server from an application), establish relationships, and propagate contextual data.
  2. Compliance Controls (data/compliance/*.toml): These files codify security and governance policies. They are processed after the architectural model is built and apply powerful mutations, such as enriching relations, inserting security intermediaries (like firewalls), and linking assets to policies.
  3. Report Definitions (data/reports/*.toml): These files define how to generate structured data artifacts (e.g., JSON reports) from the final graph. They are processed last, allowing them to query the fully modeled and governed digital twin.

This guide details the syntax, options, and graph impact of every available directive in these files.


2. Architectural Modeling (data/models/*.toml)

Model files are the core of the architectural blueprint. Each file typically defines a new type of resource (a “model”) and its relationship to an existing resource type.

2.1. File Header

Every model file begins with a header section that defines the core relationship for the rules within that file.

Key Mandatory Type Description
origin_resource Yes String The type of the existing resource type (e.g., application). This is the resource the rules in the file will primarily operate on.
disable_auto_relations No Boolean If true, resources created by this model file are opted-out of the automatic relation creation described in section 2.5. Defaults to false.
(any name) No TOML Table / Array / String A custom key to provide data for use in templates. This can be an inline TOML table/array, or a reference to an external file using json!("path/to/file.json"). Any top-level key that is not a standard model directive (like origin_resource, create_resource, etc.) will be treated as injectable data for templates.

Example: data/models/server.toml

# The origin resource type from a CSV file.
origin_resource = "application"

# This key is not a standard directive, so it's treated as JSON data.
server_configs = {
  "standard" = { cpus = 4, memory_gb = 16 },
  "large" = { cpus = 8, memory_gb = 64 }
}

2.2. Resource Creation Directives

[[create_resource]]

This is the primary directive for creating new resources in the graph. It is highly flexible, supporting both unconditional and conditional logic. It is defined as an array of tables ([[...]]) to allow multiple rules within a single file.

Option Method Mandatory Type Description
match_on [[create_resource]] Conditional Array of Tables An array of filter objects. The rule applies if all conditions match (AND logic). If omitted, the rule applies unconditionally.
resource_type [[create_resource]] Conditional String The type for the new resource. Mandatory unless using create_from_property.
relation_type [[create_resource]] Yes String The type for the relation connecting the origin resource to the new resource.
name [[create_resource]] Conditional String Template A template for the primary key of the new resource. Mandatory when using resource_type.
properties [[create_resource]] Optional TOML Table A key-value map of properties to add to the new resource. String values support templates.
relation_properties [[create_resource]] Optional TOML Table A key-value map of properties to add to the new relation.
create_from_property [[create_resource]] Conditional String Creates a resource from a property’s name (as label) and value (as primary key). An alternative to resource_type and name.
property_origin [[create_resource]] Optional String When using create_from_property, specifies the type of a related resource from which to read the property. Defaults to the origin_resource_type.
relation_origin [[create_resource]] Optional String When using create_from_property, controls the origin of the new relation. Can be "origin_resource" (the file’s top-level origin) or "property_origin" (the resource where the property was found, default).

Example 1: Unconditional Creation (data/models/server.toml)

This rule creates one server resource for every application resource.

origin_resource = "application"

[[create_resource]]
resource_type = "server"
relation_type = "DEFINED_BY"
name = "{{origin_resource.name}}_server"
[create_resource.properties]
description = "The {{origin_resource.name}} server is DEFINED_BY the application {{origin_resource.name}}."

Example 2: Conditional Creation (data/models/classification.toml)

origin_resource = "subscription"

# Rule 1: Match on multiple properties
[[create_resource]]
match_on = [
  { property = "environment", value = "prod" },
  { property = "provider", value = "Oracle" }
]
resource_type = "classification"
relation_type = "IS_CLASSIFIED_AS"
name = "{{origin_resource.subscription}}_prod_oracle_classification"
[create_resource.properties]
level = "Highly Restricted (Oracle Prod)"

# Rule 2: Match on a single property
[[create_resource]]
match_on = [
  { property = "environment", value = "dev" }
]
resource_type = "classification"
relation_type = "IS_CLASSIFIED_AS"
name = "{{origin_resource.subscription}}_dev_classification"
[create_resource.properties]
level = "Internal"

The match object inside the match_on array supports several operators. String-based values (value, not, contains) support templating.

Key Type Description
property String Mandatory. The name of the property on the source resource to match against.
value String, Boolean, Number Performs an exact, type-aware match (equality) on the property’s value.
not String, Boolean, Number The condition is true if the property’s value is not equal to this value.
contains String For a string property, checks if it contains the substring. For an array property, checks if it contains this value as an element.
exists Boolean If true, the condition is true if the property exists and is not null or an empty string. If false, it’s true if the property does not exist, is null, or is an empty string.
empty Boolean If true, the condition is true if the property is missing, null, an empty string (""), or an empty array ([]). If false, it’s true if the property has a value.
greater Number For a numeric property, checks if its value is greater than this number (>).
lower Number For a numeric property, checks if its value is less than this number (<).

All specified conditions in a single match object must be true for the match to succeed (AND logic).

  • Graph Impact:
    1. For each subscription resource, the importer evaluates the [[create_resource]] rules.
    2. If a subscription has environment = "dev", a new classification resource is created with level = "Internal".
    3. If a subscription has both environment = "prod" and provider = "Oracle", a classification resource with level = "Highly Restricted..." is created.
    4. An relation with the type IS_CLASSIFIED_AS is created from the subscription resource to the newly created classification resource.

Advanced Logic with or blocks

To support more complex conditional logic, you can use a nested or block within the match_on array. This allows for OR conditions, where the top-level match_on array remains an AND list.

The structure is { or = [ [...] ] }, where the or key holds an array of arrays. Each inner array is a set of conditions that are evaluated with AND logic. The outer array is evaluated with OR logic.

Example: Match if status is “active” AND (cores > 8 OR legacy_system is false)

# [[create_resource]]
match_on = [
  # Standard AND condition
  { property = "status", value = "active" },

  # OR block, also AND'd with the condition above
  { or = [ [ { property = "cores", greater = 8 } ], [ { property = "legacy_system", value = "false" } ] ] }
]

create_from_property

As an alternative to resource_type and name, this directive provides a concise, convention-based way to create resources. It uses a property from an existing resource, where the property’s name becomes the new resource’s type (label), and the property’s value becomes its primary key.

Handling Arrays and Comma-Separated Strings: If the property’s value is an array of strings (e.g., ["pkg1", "pkg2"] in JSON) or a comma-separated string (e.g., "pkg1, pkg2" in a CSV file), this directive will iterate through each item in the list. For each item, it will create (or link to) a separate resource. This is a powerful way to model one-to-many relationships from a single property. The {{ property.value }} variable in the name will be pkg1 in the first iteration and pkg2 in the second.

Example 1: Basic Use Case (from the source node)

Assume application.csv has a service column. This rule will automatically create service resources.

# data/models/application_services.toml
origin_resource = "application"

[[create_resource]]
create_from_property = "service"
relation_type = "PROVIDES"
  • Graph Impact: For an application with service = "replication", this creates a (service {service: "replication"}) resource and links them with a PROVIDES relation.

Example 2: Advanced Use Case (from a related node)

This is useful for creating resources based on data further down a relationship chain. Within the subscription.toml model, we can create a service resource based on the related application’s property and link it back to the original subscription.

# data/models/subscription_services.toml
origin_resource = "subscription"

[[create_resource]]
# 1. Traverse from 'subscription' to the related 'application' resource.
property_origin = "application"

# 2. On the 'application' resource, find the 'service' property.
create_from_property = "service"
relation_type = "USES"

# 3. Define the origin of the new relation to be the top-level origin_resource.
relation_origin = "origin_resource"

2.3. Property Propagation and Enrichment

These directives move data between resources, enriching the graph with valuable context.

[[subscribe_property]]

This directive copies a property value from an existing resource to a directly connected target resource. It’s essential for propagating context along a path in the graph. It can be applied conditionally using match_on on the target resource.

Option Method Mandatory Type Description
origin_resource_type [[subscribe_property]] Yes String The type of the resource to copy the property from. Defaults to the file’s origin_resource_type.
origin_property [[subscribe_property]] Yes String The name of the property to copy from the origin resource.
target_resource_type [[subscribe_property]] Optional String The type of the resource to copy the property to.
target_property [[subscribe_property]] Yes String The name of the new property on the target resource.
match_on [[subscribe_property]] Optional Array of Tables An array of { property = "...", value = "..." } tables. The rule applies only if all conditions match on the target_resource_type resource. If omitted, the rule applies unconditionally.
aggregate [[subscribe_property]] Optional Boolean If true, when multiple source nodes subscribe to the same target property, all unique values are collected into an array. The result is always an array, even for a single value. Defaults to false.
common [[subscribe_property]] Optional Boolean If true, finds the intersection (common values) from all source properties and stores them in an array. The result is always an array. Defaults to false.

Example: data/models/subscription.toml

origin_resource = "subscription"

[[subscribe_property]]
origin_resource_type = "application"       # Copy FROM the connected 'application'
origin_property = "network"
target_resource_type = "subscription" # Copy TO the 'subscription'
target_property = "network"

When a single target resource has a property subscribed from multiple source resources, the importer handles value combination as follows:

  • Default Behavior: If neither aggregate nor common is specified, the importer collects all unique values. If only one unique value is found, it is stored as a scalar (e.g., a string or number). If multiple unique values are found, they are stored as an array.

  • With aggregate = true: All unique values from all sources are collected into an array. The result is always an array, even if there is only one value.

  • With common = true: Only the values that are present in the property of every source node are collected. The result is always an array representing the intersection of values.

  • Graph Impact: After the initial relations are created, the importer finds every subscription resource. It traverses its outgoing relation to find a connected application resource. It then copies the value of the network property from the application resource to a new network property on the subscription resource.

[[enrich_property]]

This powerful directive performs a “join” across the graph. It enriches a base resource by finding another, potentially unrelated, resource with a matching key and copying a property from it. It can be applied conditionally using match_on on the base resource.

Option Method Mandatory Type Description
from_resource_type [[enrich_property]] Yes String The type of the resource to get the data FROM.
origin_key [[enrich_property]] Yes String The property name on the base resource (origin_resource) to use for the join.
target_key [[enrich_property]] Yes String The property name on the join resource (from_resource_type) to use for the join.
property_to_copy [[enrich_property]] Conditional String The name of the property to copy. At least one of property_to_copy or relation_type must be specified.
relation_type [[enrich_property]] Conditional String The type of the relation to create. At least one of property_to_copy or relation_type must be specified.
reverse_relation [[enrich_property]] Optional Boolean If true (default), the created relation is directed from the joined resource (from_resource_type) to the base resource (origin_resource). If false, the direction is from base to joined. Replaces the deprecated relation_origin key (relation_origin = "join_resource" is equivalent to reverse_relation = true).
match_on [[enrich_property]] Optional Array of Tables An array of { property = "...", value = "..." } tables. The rule applies only if all conditions match on the base resource (origin_resource). If omitted, the rule applies unconditionally.

Example: data/models/subscription.toml

origin_resource = "subscription"
# ...
[[enrich_property]]
from_resource_type = "location"
origin_key = "location"      # Property on 'subscription'
target_key = "name"         # Property on 'location'
property_to_copy = "compliance"
  • Graph Impact: For every subscription resource, the importer takes the value of its location property (e.g., “FRA”). It then searches for a location resource whose name property also equals “FRA”. If a match is found, it copies the value of the compliance property from the location resource to the subscription resource.

2.4. Advanced Directives

Advanced Templating (Tera)

The system uses the powerful Tera templating engine, which allows for much more than simple variable replacement. You can use logic, filters, and loops directly within your TOML string values.

Accessing Data

You can access data from the origin_resource and any custom data sources (inline TOML or external JSON) defined in the header.

# In header
server_specs = json!("data/server_specs.json")

inline_configs = { prod_tier = "Gold", dev_tier = "Bronze" }

[create_resource.properties]
# Access a property from the resource being processed
description = "Server for {{ origin_resource.name }}."
# Access a nested value from an external JSON file
cpu_arch = "{{ server_specs.x86_64.vendor }}"
# Access a value from an inline TOML table
tier = "{{ inline_configs.prod_tier }}"
Using Filters

Tera provides a wide range of built-in filters to manipulate data. You can chain them using the | pipe character. A full list is available in the Tera documentation.

[create_resource.properties]
# Convert a property to uppercase
hostname_prefix = "{{ origin_resource.name | upper }}"

# Get the number of items in an array property
num_tags = "{{ origin_resource.tags | length }}"

# Replace characters in a string
sanitized_name = "{{ origin_resource.name | replace(from=\".\", to=\"-\") }}"
Conditional Logic with if/else

Use {% if ... %} blocks to conditionally render parts of a string. This is extremely powerful for creating dynamic properties.

[create_resource.properties]
# Set a property based on another property's value
sla_level = "{% if origin_resource.environment == 'prod' %}Gold{% else %}Silver{% endif %}"

# Set a property based on the existence of another
backup_policy = "{% if origin_resource.backup_enabled is defined and origin_resource.backup_enabled %}Standard{% else %}None{% endif %}"
Loops with for

You can iterate over arrays from your context to build up strings.

[create_resource.properties]
# Create a comma-separated list of formatted tags
tag_list = "{% for tag in origin_resource.tags %}{{ tag | upper }}{% if not loop.last %},{% endif %}{% endfor %}"
Accessing Relationship (Edge) Properties

When you traverse a relationship in a template, such as in a for loop or by index (e.g., origin_resource.image[0]), the context for the target resource is augmented with a special _relation object. This object contains the properties of the edge that connects the source resource to that target resource.

This is particularly powerful for reports, where you might want to display information about how two components are connected, including any compliance controls applied to that connection.

The _relation object has the following structure:

  • label: The label of the edge (e.g., HOSTED_IN, PROTECTED_BY).
  • (other properties): Any other key-value properties that have been added to the edge by models or compliance rules.

Example:

Assume a compliance rule has enriched the edge between a database and its application with control information. In a report template with origin_resource = "database", you could access this information like so:

The database {{ origin_resource.name }} connects to the application {{ origin_resource.application[0].name }}.
Connection Details:
- Type: {{ origin_resource.application[0]._relation.label }}
{% for control in origin_resource.application[0]._relation.controls %}
- Applied Control: {{ control.control_id }} ({{ control.audit_id }})
- Min TLS Version: {{ control.min_tls_version }}
{% endfor %}

[[retype_relation]]

This directive overrides the default relation type when an relation is created based on a foreign key in a CSV file. By default, the relation type is the same as the column header. This allows you to specify a more descriptive type.

Example: data/models/image.toml

origin_resource = "image"

# When creating an relation from an 'image' resource based on the 'util' column,
# label the relation 'HAS_UTIL' instead of 'util'.
[[retype_relation]]
property_key = "util"
new_type = "HAS_UTIL"
  • Graph Impact: When the importer processes image.csv and finds a value in the util column, instead of creating an relation with the type util, it creates an relation with the type HAS_UTIL.

Convention-Based Responsibility Mapping ([control.target.map])

This advanced pattern is designed to model ownership and responsibility across the entire graph with a single, declarative rule. Instead of creating many individual linking targets, this pattern discovers roles from the graph itself and automatically creates the appropriate relationships. It is typically defined within a compliance file (e.g., ownership.toml).

Option Method Mandatory Type Description
derived_type [control.target.map] Yes String The type of resources that define the roles to look for (e.g., “role”).
origin_resource_types [control.target.map] Yes Array of Strings An array of asset types to scan for role properties.
target_resource_type [control.target.map] Yes String The type of the resource to link to (e.g., “provider”).
primary_relation_type [control.target.map] Yes String The type for the primary relation (e.g., “HAS_RESPONSIBILITY”).
property_on_relation [control.target.map] Yes String The name of a property to add to the primary relation, with the role name as its value (e.g., role = "maintainer").
link_relation_to_target [control.target.map] No Boolean If true, creates a secondary link from the derived_type resource to the target_resource_type.
secondary_relation_type [control.target.map] No String The type for the secondary link (e.g., “IS_PERFORMED_BY”).
property_map_overrides [control.target.map] No TOML Table A map to alias property names to role names (e.g., map the vendor property to the maintainer role).

Example: Modeling Ownership with a Single Rule

This example centralizes all ownership logic for the entire graph. It defines that properties like owner, maintainer, and even vendor on an asset should all result in a HAS_RESPONSIBILITY link to a provider.

# From data/compliance/ownership.toml
[[control]]
id = "OWN-1"
name = "Map Asset Roles to Providers"
[[control.target]]
[control.target.map]
derived_type = "role"
origin_resource_types = ["application", "database"]
target_resource_type = "provider"
primary_relation_type = "HAS_RESPONSIBILITY"
property_on_relation = "role"
link_relation_to_target = true
secondary_relation_type = "IS_PERFORMED_BY"
[control.target.map.property_map_overrides]
vendor = "maintainer"
  • Graph Impact:
    1. The importer scans all application, database, etc., resources.
    2. It finds an application resource with a property vendor = "team-alpha".
    3. From property_map_overrides, it sees that the vendor property maps to the maintainer role.
    4. It finds the provider resource whose primary key is team-alpha.
    5. It creates a relation: (application) -[HAS_RESPONSIBILITY {role: "maintainer"}]-> (provider).
    6. Because link_relation_to_target is true, it also performs a second action:
    7. It finds the role resource whose primary key is maintainer (the value from the map).
    8. It creates a second relation: (role) -[IS_PERFORMED_BY]-> (provider).

2.5. Automatic Relation Creation for Model-Defined Resources

After all architectural models ([[create_resource]], etc.) have been processed, the importer performs an automatic relation creation phase. This phase is similar to the initial asset-to-asset relationship creation, but it specifically targets resources that were created by a model.

The convention is as follows:

  1. The importer identifies all resource types that were created by model files (e.g., server, service, classification).
  2. It then scans all resources in the graph (both from assets and other models).
  3. If a resource has a property whose key matches the name of a model-defined resource type, the importer treats the property’s value as a primary key.
  4. It then creates a relation from the resource to the corresponding model-defined resource.

This allows for a powerful, convention-based way to link resources without writing explicit rules for every connection.

Example: Linking a host asset to a model-defined server

  • data/models/server.toml creates server resources from application resources. A server named billing-api_server is created.
  • data/assets/host.csv defines physical hosts.
# data/assets/host.csv
name,ip_address,server
host-01,10.0.1.10,billing-api_server

During this phase, the importer processes host-01. It sees the property server = "billing-api_server". Since server is a known model-defined resource type, it creates a relation: (host:host-01) -[server]-> (server:billing-api_server).

Disabling Automatic Linking

In some cases, a property name might coincidentally match a model-defined resource type, leading to unwanted relations. You can prevent this by adding disable_autolinks = true to the header of the model file that creates the resource.

# data/models/service.toml
origin_resource = "application"
disable_autolinks = true # Resources of type 'service' will not be targets for automatic linking.

[[create_resource]]
resource_type = "service"
# ...

3. Report Generation (data/reports/*.toml)

Report files, located in data/reports/, are the final step in the processing pipeline. They allow you to query the fully constructed graph and generate new, structured data resources from it. This is ideal for creating artifacts like compliance summaries, service catalogs, or inputs for other automation systems.

Report definitions use Tera templating to render the properties of a new resource, which are often structured as a JSON object.

3.1. File Header & Output Structure

Key Method Mandatory Type Description
origin_resource Top Level Yes String The type of resource to process (e.g., application).
(any name) Top Level No TOML Table / String Custom data for use in templates, including json!("path/to/file.json").
[[output]] Top Level Yes Array of Tables An array of rules, each defining a report to generate.

Each [[output]] block defines a rule for creating a new report resource.

Option Method Mandatory Type Description
resource_type [[output]] Yes String The type of the new report resource to create (e.g., application_summary).
name [[output]] Yes String Template A template for the primary key of the new report resource.
match_on [[output]] Optional Array of Tables An array of filter objects. The report is generated only if the origin_resource matches all conditions.
template [[output]] Yes String Template A multiline string template that renders to a JSON object. This JSON object becomes the set of properties for the new report resource.

3.2. Example: Generating a Service Summary Report

This example generates a service_summary report for every application that is on the edge network and has a critical vulnerability.

data/reports/service_summary.toml

origin_resource = "application"

# Define some static data available to the template
report_metadata = { version = "1.1", author = "security-team" }

[[output]]
resource_type = "service_summary"
name = "summary-for-{{ origin_resource.name }}"
match_on = [
  { property = "network_zone", value = "edge" },
  { property = "has_critical_vulnerability", value = true }
]
# The template renders a complete JSON object. The keys and values of this
# object will become the properties of the new 'service_summary' resource.
template = """
{
  "report_author": "{{ report_metadata.author }}",
  "application_name": "{{ origin_resource.name }}",
  "tco": {{ origin_resource.tco | default(value=0) }},
  "owner": "{{ origin_resource.provider[0].name }}",
  "vulnerability_status": "CRITICAL",
  "hosting_details": {
    "platform": "{{ origin_resource.managed_k8s_cluster[0].name }}",
    "region": "{{ origin_resource.managed_k8s_cluster[0].cloud_region[0].name }}"
  }
}
"""
  • Graph Impact:
    1. The importer finds all application resources that match the match_on criteria.
    2. For each match, it renders the template string, executing all Tera logic and accessing data from the application and its connected nodes (e.g., provider, managed_k8s_cluster).
    3. The resulting string is parsed as JSON.
    4. A new service_summary resource is created. Its properties are the keys and values from the parsed JSON (e.g., report_author, tco, hosting_details).

4. Compliance as Code (data/compliance/*.toml)

Compliance files apply automated changes to the graph after the initial model is built. They are composed of one or more [[control]] blocks that define specific security rules and the actions to take on the graph.

4.1. File & Control Headers

Key Method Mandatory Type Description
audit_id Top Level Yes String A unique identifier for the audit framework (e.g., “BAFIN-VAIT”).
audit_name Top Level Optional String The human-readable name of the audit framework.
id [[control]] Yes String The unique ID of the specific control within the framework (e.g., “VAIT-7.2-Encryption”).
name [[control]] Yes String The human-readable name of the control.
config [[control]] Optional TOML Table A key-value store for parameters related to this control. These values are used by the target blocks.
(any name) Top Level No TOML Table / Array / String A custom key to provide JSON data for use in templates. Can be an inline TOML table/array, or a reference to an external file using json!("path/to/file.json").

4.2. Targeting and Mutation Patterns ([[control.target]])

The [[control.target]] array defines where and how to apply a control. Each target block implements a specific graph mutation pattern.

Pattern 1: Enriching Relations

This pattern adds properties to existing relations to model the nature of a connection (e.g., protocol requirements).

TOML Keys:

  • relation_origin_type: The type of the resource at the start of the relation.
  • relation_target_type: The type of the resource at the end of the relation.
  • properties_from_config: An array of strings. Each string is a key from the [control.config] block whose value will be copied as properties onto the relation.

Example: data/compliance/bafin.toml

[[control]]
id = "VAIT-7.2-Encryption"
[control.config]
min_tls_version = "1.2"
required = true

[[control.target]]
relation_origin_type = "application"
relation_target_type = "database"
properties_from_config = ["min_tls_version", "required"]
  • Graph Impact: Finds every relation between an application resource and a database resource. It adds a new controls array to the relation’s properties, containing an object with min_tls_version: "1.2" and required: true.

Pattern 2: Attaching New Control Resources

This pattern models policies that apply to an asset, such as an MFA requirement on an identity.

TOML Keys:

  • origin_resource_type: The type of the origin resource to which the control applies.
  • match_on: An array of { property = "...", value = "..." } tables to filter specific source resources.
  • [control.target.resource]: Defines the new resource to create. For attachment, this block must contain a name.
    • type: Type of the new resource.
    • name: Template for the new resource’s name.
    • properties_from_config: Array of keys from [control.config] to copy as properties.
    • properties: A TOML table allowing direct definition of properties for the new resource. String values in this table can use templates to reference external JSON data or source resource properties.
  • [control.target.relation]: Defines the relation linking the source resource to the new resource.
    • type: The type of the new relation.
  • [[control.target.resource_links]]: (Optional) An array to create additional links from the new resource to other existing resources.

Example: data/compliance/iso27001.toml

[[control]]
id = "A.5.17"
# Load MFA details from an external file
mfa_input = json!("data/mfa_policy.json")

[[control]]
# ...
# [control.config] is not needed if properties are defined directly

[[control.target]]
origin_resource_type = "identity"
match_on = [
  { property = "privileged", value = "true" }
]

[control.target.resource]
type = "security_control"
name = "mfa_for_{{origin_resource.identity}}"
[control.target.resource.properties]
mfa_required = true
details = "{{mfa_input.details}}"

[control.target.relation]
type = "APPLIES_TO"

Example: data/mfa_policy.json

{
  "details": "Multi-Factor Authentication is mandatory for all privileged accounts. Acceptable factors include TOTP (Time-based One-Time Password) and FIDO2-compliant hardware tokens. Access will be denied if MFA is not configured or fails."
}
  • Graph Impact:
    1. Finds all identity resources where the property privileged is true.
    2. For each match, it creates a new security_control resource.
    3. It creates a new relation from the identity resource to the new security_control resource with the type APPLIES_TO.

Pattern 3: Inserting Resources into Connections

This pattern models intermediaries like proxies or firewalls by inserting a new resource into an existing connection.

TOML Keys:

  • relation_origin_type & relation_target_type: Identifies the relation to intercept.
  • relation_origin_match_on & relation_target_match_on: (Optional) An array of { property = "...", value = "..." } tables to filter for specific origin or target resources.
  • [control.target.resource]: Defines the intermediary resource to insert. For an insertion, this block must contain a name.
    • type: Type for the new intermediary resource.
    • name: Template for the new resource’s name.
    • properties_from_config: Properties to copy from [control.config].
    • properties: A TOML table allowing direct definition of properties, supporting templates.

Example: data/compliance/bafin.toml

[[control]]
id = "VAIT-7.3-Proxy"
[control.config]
proxy_type = "WAF"

[[control.target]]
relation_origin_type = "application"
relation_origin_match_on = [ { property = "name", value = "asseteditor" } ]
relation_target_type = "backend"
# relation_target_match_on is omitted, so it matches any backend connected to the filtered source.

[control.target.resource]
type = "reverse_proxy"
name = "proxy_for_{{origin_resource.name}}"
properties_from_config = ["proxy_type"]
  • Graph Impact:
    1. Finds the relation between the application named asseteditor and its connected backend resource.
    2. Deletes this original relation.
    3. Creates a new reverse_proxy resource.
    4. Creates a new relation from asseteditor to the new reverse_proxy.
    5. Creates a second new relation from the reverse_proxy to the original backend resource.

Pattern 4: Linking Existing Resources

This pattern establishes a new relationship between two existing resources in the graph as mandated by a control.

TOML Keys:

  • origin_resource_type: The type of the origin resource(s) from which to create the new link.
  • match_on: Filters to select specific source resources.
  • [control.target.resource]: Defines the single existing target resource. For linking, this block must contain match_on and must not contain name.
    • type: The type for the new relation.
    • match_on: An array of { property = "...", value = "..." } tables to uniquely identify the target resource. The value can be a template string to dynamically look up the target resource.
  • [control.target.relation]: Defines the new relation to create.
    • type: The type for the new relation.
    • properties_from_config: (Optional) Properties from [control.config] to add to the new relation.

Example: data/compliance/ownership.toml

[[control]]
id = "OWNERSHIP-MAP-MAINTAINER"
[control.config]
role = "maintainer"

[[control.target]]
origin_resource_type = "application"

[control.target.resource]
type = "provider"
match_on = [
  { property = "name", value = "{{origin_resource.maintainer}}" } # Dynamically finds the provider name
]

[control.target.relation]
type = "HAS_RESPONSIBILITY"
properties_from_config = ["role"]
  • Graph Impact:
    1. Finds all application resources.
    2. For each application, it reads the value of its maintainer property (e.g., “team-alpha”).
    3. It then finds the single provider resource where the name property is “team-alpha”.
    4. It creates a new relation from the application to the found provider with the type HAS_RESPONSIBILITY.
    5. It enriches the new relation with the property { "role": "maintainer" }.

Pattern 5: Convention-Based Responsibility Mapping

See the Convention-Based Responsibility Mapping ([control.target.map]) section under Architectural Modeling for a full description of this powerful pattern.