Getting Started

Quickstart: Hybrid Model & Compliance

Expand the quickstart graph with conditional platform modeling, database assets, foreign-key auto-linking, and a compliance control enforced on database connections.

Quickstart: Hybrid Model & Compliance

This page continues the Quick Start Guide. You need the my-infra-graph project from Step 1, ideally with the graph snapshot saved (step1.json) — we will diff against it at the end.

A Hybrid Cloud Model with Compliance

Goal: Expand the graph to model a hybrid environment. We will:

  1. Distinguish between on-premise and cloud applications.
  2. Use conditional logic (match_on) to create different platform resources.
  3. Introduce a new database asset and an automatic relationship.
  4. Apply a compliance control to enforce encryption on database connections.

1. Enhance the Assets

Update application.csv with platform and database columns. The database column acts as a foreign key, automatically creating a relationship to a resource defined in database.csv.

data/assets/application.csv

name,owner,runtime,platform,database
billing-api,team-alpha,java,on-prem,billing-db-prod
frontend-app,team-bravo,nodejs,cloud,user-db-prod

Now, create the database asset file.

data/assets/database.csv

name,type,version
billing-db-prod,PostgreSQL,14
user-db-prod,MySQL,8.0

2. Create a Conditional Model for Platforms

This model will read application resources and, based on the platform property, create either an onprem_datacenter or a cloud_provider resource, demonstrating how to model hybrid infrastructure.

data/models/platform.toml

origin_resource = "application"

# Rule 1: For on-premise applications.
[[create_resource]]
# This rule only applies if the application's 'platform' property is 'on-prem'.
match_on = [
  { property = "platform", value = "on-prem" }
]
resource_type = "onprem_datacenter"
relation_type = "HOSTED_IN"
name = "dc-frankfurt" # A static name for our on-prem DC
[create_resource.properties]
location = "Frankfurt"
operator = "internal-hosting"

# Rule 2: For cloud applications.
[[create_resource]]
match_on = [
  { property = "platform", value = "cloud" }
]
resource_type = "cloud_provider"
relation_type = "HOSTED_BY"
name = "aws-eu-central-1" # A static name for our cloud provider region
[create_resource.properties]
region = "eu-central-1"
vendor = "AWS"

3. Define a Compliance Control

Compliance files are processed after the main graph is built. This control will find all connections between an application and a database and enrich the connecting relation with a security requirement.

data/compliance/security.toml

audit_id = "INTERNAL-SEC-POLICY"
audit_name = "Internal Security Policy"

[[control]]
id = "SEC-DB-01"
name = "Database Encryption in Transit"

# A key-value store for control parameters.
[control.config]
min_tls_version = "1.2"
status = "mandatory"

[[control.target]]
# The control iterates over 'application' resources...
origin_resource_types = "application"
# ...but targets an existing RELATIONSHIP from each application.
# Find all relations between an 'application' and a 'database'.
relation_origin_type = "application"
relation_target_type = "database"

# Copy these keys from [control.config] onto the properties of the matched relation.
properties_from_config = ["min_tls_version", "status"]

4. Build and Verify the Hybrid Graph

Re-run the rescile-ce commands to build and view the new graph.

# Start the server to query with GraphQL
rescile-ce --data-dir ./data serve

Verification with GraphQL: Run these queries in GraphiQL at http://localhost:7600.

Query 1: Verify Hybrid Platform Creation This query checks that the conditional platform.toml model worked correctly.

query VerifyHybridPlatforms {
  # Check the on-prem application
  onPremApplication: application(filter: {name: "billing-api"}) {
    name
    onprem_datacenter {
      node {
        name
        location
      }
    }
  }
  # Check the cloud application
  cloudApplication: application(filter: {name: "frontend-app"}) {
    name
    cloud_provider {
      node {
        name
        vendor
      }
    }
  }
}
{
  "data": {
    "onPremApplication": [
      {
        "name": "billing-api",
        "onprem_datacenter": [
          {
            "node": {
              "name": "dc-frankfurt",
              "location": "Frankfurt"
            }
          }
        ]
      }
    ],
    "cloudApplication": [
      {
        "name": "frontend-app",
        "cloud_provider": [
          {
            "node": {
              "name": "aws-eu-central-1",
              "vendor": "AWS"
            }
          }
        ]
      }
    ]
  }
}

You will see billing-api is HOSTED_IN the onprem_datacenter named dc-frankfurt, while frontend-app is HOSTED_BY the cloud_provider aws-eu-central-1.

Query 2: Verify Compliance Enrichment This query checks that the security.toml control was applied to the relation between the application and the database.

query VerifyComplianceEnrichment {
  application(filter: {name: "billing-api"}) {
    name
    database {
      # The 'properties' block queries the relation itself.
      properties {
        relation
        controls # The importer groups compliance properties under 'controls'
      }
      # The 'node' block queries the connected database resources.
      node {
        name
        type
      }
    }
  }
}
{
  "data": {
    "application": [
      {
        "name": "billing-api",
        "database": [
          {
            "properties": {
              "relation": "database",
              "controls": [
                {
                  "audit_id": "INTERNAL-SEC-POLICY",
                  "audit_name": "Internal Security Policy",
                  "control_id": "SEC-DB-01",
                  "control_name": "Database Encryption in Transit",
                  "min_tls_version": 1.2,
                  "status": "mandatory"
                }
              ]
            },
            "node": {
              "name": "billing-db-prod",
              "type": "PostgreSQL"
            }
          }
        ]
      }
    ]
  }
}

The result will show the database relation with a controls array containing an object with audit_id: "INTERNAL-SEC-POLICY", min_tls_version: "1.2", and status: "mandatory".

The final graph should look like this:

graph TD
    subgraph "Cloud Resources"
        AppCloud["application<br><b>frontend-app</b>"]
        DBCloud["database<br><b>user-db-prod</b>"]
        PlatformCloud["cloud_provider<br><b>aws-eu-central-1</b>"]
        AppCloud -- "database<br><b>{ controls: ... }</b>" --> DBCloud
        AppCloud -- "HOSTED_BY" --> PlatformCloud
    end

    subgraph "On-Premise Resources"
        AppOnPrem["application<br><b>billing-api</b>"]
        DBOnPrem["database<br><b>billing-db-prod</b>"]
        PlatformOnPrem["onprem_datacenter<br><b>dc-frankfurt</b>"]
        AppOnPrem -- "database<br><b>{ controls: ... }</b>" --> DBOnPrem
        AppOnPrem -- "HOSTED_IN" --> PlatformOnPrem
    end

If the state has been saved in the previous step, we can run a comparison.

# Start the graph diff
rescile-ce --data-dir ./data diff step1.json
[...]

Comparing graph step1.json with current in-memory graph

Structural Graph Comparison Result

Resources Added:
  (+) frontend-app (type: application)
  (+) INTERNAL-SEC-POLICY (type: audit)
  (+) aws-eu-central-1 (type: cloud_provider)
  (+) SEC-DB-01 (type: control)
  (+) billing-db-prod (type: database)
  (+) user-db-prod (type: database)
  (+) dc-frankfurt (type: onprem_datacenter)
  (+) frontend-app_server (type: server)

Relations Added:
  (+) (application `billing-api`) --[database]--> (database `billing-db-prod`)
  (+) (application `billing-api`) --[HOSTED_IN]--> (onprem_datacenter `dc-frankfurt`)
  (+) (application `frontend-app`) --[HOSTED_BY]--> (cloud_provider `aws-eu-central-1`)
  (+) (application `frontend-app`) --[database]--> (database `user-db-prod`)
  (+) (application `frontend-app`) --[RUNS_ON]--> (server `frontend-app_server`)
  (+) (control `SEC-DB-01`) --[BELONGS_TO]--> (audit `INTERNAL-SEC-POLICY`)


Continue with Quickstart: Graph Applications & Outlook — serve a live dashboard straight from the graph.