From fae91511442860c77b2e076bf2e9cc8fb0246243 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 1 Mar 2026 18:07:56 +0100 Subject: [PATCH] feat(sbom): add Terraform .terraform.lock.hcl parser; ingest railiance repos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ingest_sbom.py: parse .terraform.lock.hcl provider blocks (name, version); ecosystem stored as 'other' until terraform added to DB ENUM - Registered railiance-bootstrap + railiance-hosts under railiance domain - railiance-hosts ingested: 2 Terraform providers (hashicorp/template 2.2.0, hetznercloud/hcloud 1.52.0) - railiance-bootstrap: no lockfile (pure Ansible/shell — noted in convention) - sbom-convention_v0.1.md: add Terraform + Ansible rows to lockfile table; update registered repos status table Total SBOM: 422 packages across 2 repos (custodian + railiance-hosts) Co-Authored-By: Claude Sonnet 4.6 --- scripts/ingest_sbom.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/scripts/ingest_sbom.py b/scripts/ingest_sbom.py index 59ce949..c024ac8 100644 --- a/scripts/ingest_sbom.py +++ b/scripts/ingest_sbom.py @@ -180,12 +180,47 @@ def _parse_cargo_lock(path: Path) -> list[dict]: ] +def _parse_terraform_lock_hcl(path: Path) -> list[dict]: + """Parse .terraform.lock.hcl — extract Terraform provider name + version.""" + entries = [] + current_name: str | None = None + current_version: str | None = None + + for line in path.read_text().splitlines(): + stripped = line.strip() + # e.g.: provider "registry.terraform.io/hetznercloud/hcloud" { + m = re.match(r'^provider\s+"([^"]+)"\s*\{', stripped) + if m: + # Use full provider address as package_name, short name as display + full = m.group(1) + current_name = full # e.g. "registry.terraform.io/hetznercloud/hcloud" + current_version = None + elif current_name is not None: + vm = re.match(r'version\s*=\s*"([^"]+)"', stripped) + if vm: + current_version = vm.group(1) + elif stripped == "}": + entries.append({ + "package_name": current_name, + "package_version": current_version, + "ecosystem": "other", # "terraform" not yet in ENUM; tracked as other + "license_spdx": None, + "is_direct": True, + "is_dev": False, + }) + current_name = None + current_version = None + + return entries + + _LOCKFILE_PARSERS = { "uv.lock": _parse_uv_lock, "requirements.txt": _parse_requirements_txt, "package-lock.json": _parse_package_lock_json, "yarn.lock": _parse_yarn_lock, "Cargo.lock": _parse_cargo_lock, + ".terraform.lock.hcl": _parse_terraform_lock_hcl, } # Directories that never contain project-level lockfiles