Skip to content

Commit 6e1ad2a

Browse files
author
Tamas Vajk
committed
Add cargo-auditable support for dependency SBOM embedding
Embeds cargo-auditable compatible dependency metadata (.dep-v0 section) into Rust binaries and shared libraries. When enabled via --@rules_rust//rust/settings:auditable=true, the build generates a JSON dependency manifest, zlib-compresses it, and links it into the binary as a .dep-v0 ELF section. This enables vulnerability scanning tools like trivy/syft to extract dependency information from compiled binaries. Key changes: - New auditable_injector tool that generates platform-appropriate .dep-v0 object files from JSON dependency manifests - CrateInfo provider extended with pkg_name, version, and source fields - New bool_flag //rust/settings:auditable to control the feature - rust_binary and rust_shared_library gain an auditable_injector attribute - Analysis tests verify action graph correctness
1 parent f31db8b commit 6e1ad2a

45 files changed

Lines changed: 3238 additions & 10 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

MODULE.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ bazel_dep(name = "apple_support", version = "1.24.1", repo_name = "build_bazel_a
2020
internal_deps = use_extension("//rust/private:internal_extensions.bzl", "i")
2121
use_repo(
2222
internal_deps,
23+
"rra",
24+
"rra__miniz_oxide-0.9.1",
25+
"rra__object-0.39.1",
2326
"rrra",
2427
"rrra__anyhow-1.0.102",
2528
"rrra__camino-1.2.2",

WORKSPACE.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
2626

2727
rust_analyzer_dependencies()
2828

29+
load("@rules_rust//tools/auditable:deps.bzl", "auditable_dependencies")
30+
31+
auditable_dependencies()
32+
2933
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
3034

3135
bazel_skylib_workspace()

cargo/private/BUILD.bazel

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
22
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
3-
load("//rust:defs.bzl", "rust_binary")
3+
4+
# Loads rust_binary directly from rust/private:rust.bzl (not //rust:defs.bzl)
5+
# to avoid a dependency cycle with the auditable_injector.
6+
# buildifier: disable=bzl-visibility
7+
load("//rust/private:rust.bzl", "rust_binary")
48

59
rust_binary(
610
name = "copy_file",

cargo/private/cargo_build_script_runner/BUILD.bazel

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test")
1+
load("//rust:defs.bzl", "rust_library", "rust_test")
2+
3+
# Loads rust_binary directly from rust/private:rust.bzl (not //rust:defs.bzl)
4+
# to avoid a dependency cycle with the auditable_injector.
5+
# buildifier: disable=bzl-visibility
6+
load("//rust/private:rust.bzl", "rust_binary")
27

38
rust_library(
49
name = "cargo_build_script_runner",

cargo/private/cargo_build_script_wrapper.bzl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ load(
77
"name_to_pkg_name",
88
_build_script_run = "cargo_build_script",
99
)
10-
load("//rust:defs.bzl", "rust_binary")
10+
11+
# Loads rust_binary directly from rust/private:rust.bzl (not //rust:defs.bzl)
12+
# to avoid a dependency cycle with the auditable_injector.
13+
# buildifier: disable=bzl-visibility
14+
load("//rust/private:rust.bzl", "rust_binary")
1115

1216
def cargo_build_script(
1317
*,

cargo/private/cargo_toml_variable_extractor/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
load("//rust:defs.bzl", "rust_binary")
1+
# Loads rust_binary directly from rust/private:rust.bzl (not //rust:defs.bzl)
2+
# to avoid a dependency cycle with the auditable_injector.
3+
# buildifier: disable=bzl-visibility
4+
load("//rust/private:rust.bzl", "rust_binary")
25

36
rust_binary(
47
name = "cargo_toml_variable_extractor",

rust/defs.bzl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,23 @@ rust_library = _rust_library
8484
rust_static_library = _rust_static_library
8585
# See @rules_rust//rust/private:rust.bzl for a complete description.
8686

87-
rust_shared_library = _rust_shared_library
88-
# See @rules_rust//rust/private:rust.bzl for a complete description.
87+
_AUDITABLE_INJECTOR_SELECT = select({
88+
str(Label("//rust/settings:auditable_enabled")): str(Label("//tools/auditable:auditable_injector")),
89+
"//conditions:default": None,
90+
})
91+
92+
def rust_shared_library(name, **kwargs):
93+
"""Builds a Rust shared library. See @rules_rust//rust/private:rust.bzl for a complete description."""
94+
kwargs.setdefault("auditable_injector", _AUDITABLE_INJECTOR_SELECT)
95+
_rust_shared_library(name = name, **kwargs)
8996

9097
rust_proc_macro = _rust_proc_macro
9198
# See @rules_rust//rust/private:rust.bzl for a complete description.
9299

93-
rust_binary = _rust_binary
94-
# See @rules_rust//rust/private:rust.bzl for a complete description.
100+
def rust_binary(name, **kwargs):
101+
"""Builds a Rust binary crate. See @rules_rust//rust/private:rust.bzl for a complete description."""
102+
kwargs.setdefault("auditable_injector", _AUDITABLE_INJECTOR_SELECT)
103+
_rust_binary(name = name, **kwargs)
95104

96105
rust_library_group = _rust_library_group
97106
# See @rules_rust//rust/private:rust.bzl for a complete description.

rust/private/common.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ def _create_crate_info(**kwargs):
6161
kwargs.update({"rustc_env_files": []})
6262
if not "data" in kwargs:
6363
kwargs.update({"data": depset([])})
64+
if not "pkg_name" in kwargs:
65+
kwargs.update({"pkg_name": kwargs.get("name", "")})
66+
if not "version" in kwargs:
67+
kwargs.update({"version": "0.0.0"})
68+
if not "source" in kwargs:
69+
kwargs.update({"source": "Local"})
6470
return CrateInfo(**kwargs)
6571

6672
rust_common = struct(

rust/private/internal_extensions.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
load("@bazel_features//:features.bzl", "bazel_features")
44
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
55
load("//rust/private:repository_utils.bzl", "TINYJSON_KWARGS")
6+
load("//tools/auditable:deps.bzl", "auditable_dependencies")
67
load("//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
78

89
def _internal_deps_impl(module_ctx):
@@ -14,6 +15,7 @@ def _internal_deps_impl(module_ctx):
1415
direct_deps = [struct(repo = "rules_rust_tinyjson", is_dev_dep = False)]
1516
http_archive(**TINYJSON_KWARGS)
1617

18+
direct_deps.extend(auditable_dependencies())
1719
direct_deps.extend(rust_analyzer_dependencies())
1820

1921
# is_dev_dep is ignored here. It's not relevant for internal_deps, as dev

rust/private/providers.bzl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,21 @@ CrateInfo = provider(
3434
"name": "str: The name of this crate.",
3535
"output": "File: The output File that will be produced, depends on crate type.",
3636
"owner": "Label: The label of the target that produced this CrateInfo",
37+
"pkg_name": "str: The Cargo package name, which may differ from the Rust crate name (e.g. 'rustls-webpki' vs 'webpki').",
3738
"proc_macro_deps": "depset[DepVariantInfo]: This crate's rust proc_macro dependencies' providers.",
3839
"root": "File: The source File entrypoint to this crate, eg. lib.rs",
3940
"rustc_env": "Dict[String, String]: Additional `\"key\": \"value\"` environment variables to set for rustc.",
4041
"rustc_env_files": "[File]: Files containing additional environment variables to set for rustc.",
4142
"rustc_output": "File: The output from rustc from producing the output file. It is optional.",
4243
"rustc_rmeta_output": "File: The rmeta file produced for this crate. It is optional.",
44+
"source": "str: The source of this crate (e.g. 'CratesIo', 'Git', 'Local', 'Registry').",
4345
"srcs": "depset[File]: All source Files that are part of the crate.",
4446
"std_dylib": "File: libstd.so file",
4547
"type": (
4648
"str: The type of this crate " +
4749
"(see [rustc --crate-type](https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit))."
4850
),
51+
"version": "str: The semver version of this crate.",
4952
"wrapped_crate_type": (
5053
"str, optional: The original crate type for targets generated using a previously defined " +
5154
"crate (typically tests using the `rust_test::crate` attribute)"

0 commit comments

Comments
 (0)