Tutorial Part 3: Digital Supply Chain (SCA)

Model the software supply chain from source code to dependencies.


Part 3: Digital Supply Chain: Software Composition Analysis (SCA)

Goal: In this section, we will model the software supply chain for our applications. We’ll trace the path from source code repository to running artifacts and their third-party dependencies. This creates a foundation for vulnerability management and risk analysis.

Step 9: Modeling Source Code and Artifacts

A modern supply chain starts with source code and produces immutable build artifacts (like container images or VM templates). Let’s model these connections.

First, add repository and container_image columns to application.csv.

data/assets/application.csv (add new columns)

name,type,network_zone,environment,database,supported_runtimes,microservices,repository,container_image
billing-legacy,monolith,backend,production,oracle-db1,"java, tomcat",,billing-legacy-repo,
order-frontend,container,edge,production,aurora-main,"nodejs","auth-service,payment-service,order-api",order-frontend-repo,order-frontend-img:v1.2.3
image-processor,function,backend,production,,"nodejs, python",,image-processor-repo,
billing-legacy-dev,monolith,backend,development,oracle-db1,"java, tomcat",,billing-legacy-repo,

Next, create new asset files for these repositories and container images in data/assets/.

data/assets/repository.csv

name,url,vcs_provider
billing-legacy-repo,https://git.example.com/legacy/billing,gitlab
order-frontend-repo,https://git.example.com/frontend/orders,gitlab
image-processor-repo,https://git.example.com/processing/images,gitlab

data/assets/container_image.csv

name,registry,digest
order-frontend-img:v1.2.3,ecr.example.com/frontend,sha256:abc...def

Run rescile-ce serve.

Result: rescile’s automatic relationship discovery kicks in again. Because the column names repository and container_image in application.csv match the new filenames, the graph now links applications to their source code and build artifacts. This creates a traceable software supply chain.

graph TD Repo["repository
order-frontend-repo"] --> App["application
order-frontend"] App --> Img["container_image
order-frontend-img:v1.2.3"]

Note: By default, rescile creates an incoming edge to the application. The direction can be changed if needed, but the relationship is established.

Step 10: Ingesting a Software Bill of Materials (SBOM)

An SBOM lists all the software components inside a build artifact. Let’s model the contents of our order-frontend container image.

First, add a components column to container_image.csv containing a comma-separated list of packages.

data/assets/container_image.csv (add components column)

name,registry,digest,components
order-frontend-img:v1.2.3,ecr.example.com/frontend,sha256:abc...def,"log4j:log4j-core:2.17.1,org.springframework.boot:spring-boot:2.6.3"

Next, create sbom_component.csv to define these components. We use a structured name (like a Maven coordinate) as the primary key.

data/assets/sbom_component.csv

name,vendor,license
log4j:log4j-core:2.17.1,apache,Apache-2.0
org.springframework.boot:spring-boot:2.6.3,pivotal,Apache-2.0

Finally, create an sbom.toml model to link the container image to its components using create_from_property.

data/models/sbom.toml

origin_resource = "container_image"

[[create_resource]]
# Read the 'components' property, which is a comma-separated string.
create_from_property = "components"
# The property name 'components' does not match the target resource type 'sbom_component'.
# So we must specify the target type explicitly.
resource_type = "sbom_component"
relation_type = "CONTAINS"

Run rescile-ce serve.

Result: The (container_image) node is now connected to (sbom_component) nodes for log4j and spring-boot. Our blueprint now models the internal composition of our application’s artifact.

graph TD Img["container_image
order-frontend-img:v1.2.3"] Img -- CONTAINS --> C1["sbom_component
log4j:log4j-core:2.17.1"] Img -- CONTAINS --> C2["sbom_component
spring-boot:2.6.3"]

Step 11: Enriching with Vulnerability Data

The final step is to make our blueprint “vulnerability aware.” We will ingest external vulnerability data and join it with our SBOM components.

Create a cve.csv file. This represents data you might get from a security scanner or threat intelligence feed.

data/assets/cve.csv

name,cve_id,severity,package_name
CVE-2021-44228,CVE-2021-44228,CRITICAL,log4j:log4j-core:2.17.1

Now, create a model that uses enrich_property. This powerful directive performs a join across the graph. It will find all (sbom_component) nodes and, for each one, look for a (cve) node where the package_name matches. If found, it copies the cve_id and severity properties over.

data/models/cve_enrichment.toml

origin_resource = "sbom_component"

[[enrich_property]]
# The resource type to get data FROM.
from_resource_type = "cve"
# The property on the base node (sbom_component) to join on.
origin_key = "name"
# The property on the join node (cve) to join on.
target_key = "package_name"
# The property to copy from the 'cve' node.
property_to_copy = "cve_id"

[[enrich_property]]
from_resource_type = "cve"
origin_key = "name"
target_key = "package_name"
property_to_copy = "severity"

Run rescile-ce serve.

Result: The (sbom_component) node for log4j is now enriched with vulnerability data. Our blueprint has connected a CVE directly to the software component it affects, inside a container image, which is used by an application.

You can verify this with a full-stack query:

query TraceVulnerability {
  application(filter: {name: "order-frontend"}) {
    name
    container_image {
      node {
        name
        sbom_component {
          node {
            name
            cve_id
            severity
          }
        }
      }
    }
  }
}

This query traces from the application all the way down to the vulnerable component, demonstrating a complete and queryable digital supply chain.