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.
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.
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.