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:
- 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., aserverfrom anapplication), establish relationships, and propagate contextual data. - 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. - 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:
- For each
subscriptionresource, the importer evaluates the[[create_resource]]rules. - If a
subscriptionhasenvironment = "dev", a newclassificationresource is created withlevel = "Internal". - If a
subscriptionhas bothenvironment = "prod"andprovider = "Oracle", aclassificationresource withlevel = "Highly Restricted..."is created. - An relation with the type
IS_CLASSIFIED_ASis created from thesubscriptionresource to the newly createdclassificationresource.
- For each
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 aPROVIDESrelation.
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
aggregatenorcommonis 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
subscriptionresource. It traverses its outgoing relation to find a connectedapplicationresource. It then copies the value of thenetworkproperty from theapplicationresource to a newnetworkproperty on thesubscriptionresource.
[[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
subscriptionresource, the importer takes the value of itslocationproperty (e.g., “FRA”). It then searches for alocationresource whosenameproperty also equals “FRA”. If a match is found, it copies the value of thecomplianceproperty from thelocationresource to thesubscriptionresource.
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.csvand finds a value in theutilcolumn, instead of creating an relation with the typeutil, it creates an relation with the typeHAS_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:
- The importer scans all
application,database, etc., resources. - It finds an
applicationresource with a propertyvendor = "team-alpha". - From
property_map_overrides, it sees that thevendorproperty maps to themaintainerrole. - It finds the
providerresource whose primary key isteam-alpha. - It creates a relation:
(application) -[HAS_RESPONSIBILITY {role: "maintainer"}]-> (provider). - Because
link_relation_to_targetis true, it also performs a second action: - It finds the
roleresource whose primary key ismaintainer(the value from the map). - It creates a second relation:
(role) -[IS_PERFORMED_BY]-> (provider).
- The importer scans all
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:
- The importer identifies all resource types that were created by model files (e.g.,
server,service,classification). - It then scans all resources in the graph (both from assets and other models).
- 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.
- 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.tomlcreatesserverresources fromapplicationresources. A server namedbilling-api_serveris created.data/assets/host.csvdefines 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:
- The importer finds all
applicationresources that match thematch_oncriteria. - For each match, it renders the
templatestring, executing all Tera logic and accessing data from theapplicationand its connected nodes (e.g.,provider,managed_k8s_cluster). - The resulting string is parsed as JSON.
- A new
service_summaryresource is created. Its properties are the keys and values from the parsed JSON (e.g.,report_author,tco,hosting_details).
- The importer finds all
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
applicationresource and adatabaseresource. It adds a newcontrolsarray to the relation’s properties, containing an object withmin_tls_version: "1.2"andrequired: 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 aname.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:
- Finds all
identityresources where the propertyprivilegedistrue. - For each match, it creates a new
security_controlresource. - It creates a new relation from the
identityresource to the newsecurity_controlresource with the typeAPPLIES_TO.
- Finds all
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 aname.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:
- Finds the relation between the
applicationnamedasseteditorand its connectedbackendresource. - Deletes this original relation.
- Creates a new
reverse_proxyresource. - Creates a new relation from
asseteditorto the newreverse_proxy. - Creates a second new relation from the
reverse_proxyto the originalbackendresource.
- Finds the relation between the
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 containmatch_onand must not containname.type: The type for the new relation.match_on: An array of{ property = "...", value = "..." }tables to uniquely identify the target resource. Thevaluecan 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:
- Finds all
applicationresources. - For each
application, it reads the value of itsmaintainerproperty (e.g., “team-alpha”). - It then finds the single
providerresource where thenameproperty is “team-alpha”. - It creates a new relation from the
applicationto the foundproviderwith the typeHAS_RESPONSIBILITY. - It enriches the new relation with the property
{ "role": "maintainer" }.
- Finds all
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.