Instances and Roles
Instances represent the systems that participate in a CRADLE scenario.
The instances() block declares the systems used by the scenario. Each declared system is then defined in a matching instance("name") block.
For example:
instances() >
instance("Client"),
instance("Router").
The corresponding instance definitions can then describe the operating system, associated objects, configurations, roles and other instance-specific properties.
Instance properties
The current CRADLE reference documents the following instance-related properties:
| Property | Arguments | Status | Description |
|---|---|---|---|
instance | Instance name | Structural | Declares an instance. Repeat for multiple systems. |
os | Platform, version, architecture | Schema required | Describes the operating system. |
object | Object name | Schema required | Associates a declared object with the instance. Repeat for multiple objects. |
config | Configuration name | Compiler extension | Associates a predefined configuration with the instance. Repeat for multiple configurations. |
io | I/O definition name | Compiler extension | Associates a predefined input/output definition with the instance. |
role | Collection, role, variable map | Schema optional | Associates a predefined role. Variables are optional typed key = value pairs. |
description | Text | Compiler extension | Provides a human-readable description of the instance. |
heuristic | Framework, identifier | Compiler extension | Associates the instance with an external classification or framework identifier. |
Declare instances
Instances are declared in the instances() block.
For example:
instances() >
instance("Client"),
instance("Router").
This declares two systems:
- Client
- Router
Each declared instance should have a matching named definition.
For example:
instance("Client") >
os("ubuntu", "20.04").
and:
instance("Router") >
os("ubuntu", "20.04").
Instance names are cross-references. Keep spelling and capitalization consistent between the instances() declaration and every later reference.
Define an instance
A named instance block has the form:
instance("name") >
...
For example:
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript"),
description("Example client system").
This definition:
- identifies the instance as
Client - selects Ubuntu 20.04
- associates the
InitializationScriptobject - adds a human-readable description
Operating system
Use os() to describe the operating system associated with an instance.
The documented form is:
os("platform", "version")
For example:
os("ubuntu", "20.04")
A complete instance example is:
instance("Client") >
os("ubuntu", "20.04").
Operating-system availability can depend on the backend and target environment used to generate target-specific files.
Associate objects with an instance
Use object() inside an instance definition to associate a declared object with that instance.
For example:
instance("Client") >
object("InitializationScript").
The object should also be declared in metadata():
metadata() >
object("InitializationScript").
and defined in its own object block:
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
The relationship is:
Multiple objects can be associated with the same instance by repeating the property.
For example:
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript"),
object("CollectEvidence").
Configurations
Use config() to associate a predefined configuration with an instance.
For example:
instance("Router") >
os("ubuntu", "20.04"),
config("linux-router").
Multiple configurations can be requested by repeating config():
instance("Client") >
os("ubuntu", "20.04"),
config("linux-tcpdump"),
config("ubuntu-focal-auditd"),
config("linux-sysdig").
The canonical HelloWorld scenario uses two instance definitions. The Windows instance declares its operating system and configurations:
instance("win7") >
os("windows", "2019"),
config("win-icmpv4"),
config("win-pktmon"),
config("win-winrm"),
config("win-routing").
The router associates the object used by the scenario:
instance("router") >
os("linux", "20.04"),
object("HelloWorld").
config() is currently documented as a CradleXC compiler extension. Configuration availability depends on the environment, backend and CRADLE distribution being used.
Roles
Use role() to associate a predefined role with an instance.
The current compiler-specific form is:
role("namespace.collection", "role", { key = value })
For example:
instance("Router") >
role("example.collection", "router", {
lan = "lan_0"
}).
The three arguments represent:
| Argument | Purpose |
|---|---|
| Collection | Identifies the collection containing the role. |
| Role | Identifies the role within that collection. |
| Variables | Supplies optional role-specific values. |
In the example:
example.collection
is the collection,
router
is the role and:
lan = "lan_0" provides a role variable.
Role variables
Role variables are expressed as typed key = value pairs inside a structured map.
For example:
role("example.collection", "router", {
lan = "lan_0"
})
Where multiple variables are supported, separate them with commas.
For example:
role(
"example.collection",
"router",
{
lan = "lan_0",
mode = "example"
}
)
The interpretation of these values depends on the selected role.
Role names, collections and supported variables depend on the roles available to the CRADLE environment being used.
Description
Use description() to provide human-readable information about an instance.
For example:
instance("Client") >
os("ubuntu", "20.04"),
description("Example client system").
Descriptions do not replace the structural properties that define the instance.
They provide additional context for users reviewing the scenario.
description() is currently documented as a compiler extension for instances.
Heuristic annotations
Supported instances can use:
heuristic("framework", "identifier")
For example:
instance("Client") >
os("ubuntu", "20.04"),
heuristic("example-framework", "EXAMPLE-001").
Heuristic properties associate classification metadata with the instance.
They do not replace the underlying CRADLE definition.
See Heuristics for the documented conventions and supported use cases.
Complete instance example
The following example declares two instances and gives them different responsibilities:
instances() >
instance("Client"),
instance("Router").
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript"),
description("Example client system").
instance("Router") >
os("ubuntu", "20.04"),
config("linux-router"),
role("example.collection", "router", {
lan = "lan_0"
}).
The Client instance:
- uses Ubuntu 20.04
- associates the
InitializationScriptobject - includes a description
The Router instance:
- uses Ubuntu 20.04
- requests the
linux-routerconfiguration - associates a predefined router role
- supplies
lan_0as a role variable
Instances and networks
Instances can be connected to networks through endpoint() declarations in network blocks.
For example:
network("lan_0") >
endpoint("Client", "DHCP"),
endpoint("Router", "192.168.10.1").
The endpoint names:
- Client
- Router
refer to the instances declared earlier.
Conceptually:
lan_0Network definitions are covered in Networks and Routing.
Instances and events
Events also reference instances by name.
For example:
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", "").
Here:
instance("Client")
selects the instance associated with the event.
The instance name must resolve to an instance declared by:
instances() >
instance("Client").
Event behavior is covered in Events and Dependencies.
References between components
Consider the following scenario fragments:
metadata() >
object("InitializationScript").
instances() >
instance("Client").
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript").
network("lan_0") >
endpoint("Client", "DHCP").
event("initialize_client") >
instance("Client"),
runObject("InitializationScript", "").
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
The same names connect different parts of the scenario.
For Client:
instances()
↓
instance("Client")
↓
network endpoint
↓
event instance reference
For InitializationScript:
metadata()
↓
object definition
↓
instance association
↓
event runObject reference
A spelling or capitalization mismatch can prevent a named reference from resolving correctly.
Schema and compiler behavior
The current CRADLE schema and CradleXC behavior are not completely aligned for instance properties.
The documented differences include:
| Property | Current behavior |
|---|---|
os | Required by the current schema. |
object | Required by the current schema for associated objects. |
config | Recognized by CradleXC but not represented by the current schema in the same way. |
role | Recognized by the schema and compiler, with a compiler-specific collection, role and variables form. |
description | Recognized by CradleXC as a compiler extension. |
heuristic | Recognized by CradleXC as a compiler extension. |
Validate instance definitions against the CradleXC release you are using rather than relying on the JSON Schema alone.
Validate instance definitions
Validate the scenario with:
cxc validate -i <scenario.cradle>
For example:
cxc validate -i scenarios/HelloWorld.cradle
When an instance-related problem occurs, check:
- whether the instance was declared in
instances() - whether the named
instance()definition exists - whether names match exactly
- whether the
os()arguments are valid for the current CRADLE release - whether referenced objects are declared
- whether configurations and roles exist in the environment being used
Common mistakes
Declared instance has no matching definition
This declaration:
instances() >
instance("Client").
should have a corresponding definition:
instance("Client") >
os("ubuntu", "20.04").
Mismatched instance names
Incorrect:
instances() >
instance("Client").
instance("client") >
os("ubuntu", "20.04").
Client and client do not use the same capitalization.
Use:
instances() >
instance("Client").
instance("Client") >
os("ubuntu", "20.04").
Network references an undeclared instance
If a network contains:
endpoint("Router", "DHCP")
make sure Router has been declared:
instances() >
instance("Router").
Event references the wrong instance
If the instance is named:
Client
avoid:
event("initialize_client") >
instance("client").
Use:
event("initialize_client") >
instance("Client").
Related documentation
- Syntax and Types
- Metadata
- Networks and Routing
- Events and Dependencies
- Objects and Interpolation
- Heuristics
- First Scenario
Next steps
Continue with Networks and Routing to learn how CRADLE declares networks and connects instances to them.