-
Notifications
You must be signed in to change notification settings - Fork 16.1k
Expand file tree
/
Copy pathprotoc_authenticity.bzl
More file actions
68 lines (65 loc) · 3.12 KB
/
protoc_authenticity.bzl
File metadata and controls
68 lines (65 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"Validate that the protoc binary is authentic and not spoofed by a malicious actor."
load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/private:toolchain_helpers.bzl", "toolchains")
load("//bazel/private:prebuilt_tool_integrity.bzl", "RELEASE_VERSION")
def _protoc_authenticity_impl(ctx):
# When this flag is disabled, then users have no way to replace the protoc binary with their own toolchain registration.
# Therefore there's no validation to perform.
if not proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION:
return [OutputGroupInfo(_validation = depset())]
toolchain = ctx.toolchains[toolchains.PROTO_TOOLCHAIN]
if not toolchain:
fail("Protocol compiler toolchain could not be resolved.")
proto_lang_toolchain_info = toolchain.proto
validation_output = ctx.actions.declare_file("validation_output.txt")
ctx.actions.run_shell(
outputs = [validation_output],
tools = [proto_lang_toolchain_info.proto_compiler],
command = """\
{protoc} --version > {validation_output}
grep -q -e "-dev$" {validation_output} && {{
echo 'WARNING: Detected a development version of protoc.
Development versions are not validated for authenticity.
To ensure a secure build, please use a released version of protoc.'
exit 0
}}
grep -q "^libprotoc {RELEASE_VERSION}" {validation_output} || {{
echo '{severity}: protoc version does not match protobuf Bazel module; we do not support this.
It is considered undefined behavior that is expected to break in the future even if it appears to work today.'
echo '{suppression_note}'
echo 'Expected: libprotoc {RELEASE_VERSION}'
echo -n 'Actual: '
cat {validation_output}
exit {mismatch_exit_code}
}} >&2
""".format(
protoc = proto_lang_toolchain_info.proto_compiler.executable.path,
validation_output = validation_output.path,
RELEASE_VERSION = RELEASE_VERSION.removeprefix("v"),
suppression_note = (
"To suppress this error, run Bazel with --@com_google_protobuf//bazel/toolchains:allow_nonstandard_protoc"
if ctx.attr.fail_on_mismatch else ""
),
mismatch_exit_code = 1 if ctx.attr.fail_on_mismatch else 0,
severity = "ERROR" if ctx.attr.fail_on_mismatch else "INFO",
),
)
return [OutputGroupInfo(_validation = depset([validation_output]))]
protoc_authenticity = rule(
implementation = _protoc_authenticity_impl,
fragments = ["proto"],
attrs = {
"fail_on_mismatch": attr.bool(
default = True,
doc = "If true, the build will fail when the protoc binary does not match the expected version.",
),
} | toolchains.if_legacy_toolchain({
"_proto_compiler": attr.label(
cfg = "exec",
executable = True,
allow_files = True,
default = "//src/google/protobuf/compiler:protoc_minimal",
),
}),
toolchains = toolchains.use_toolchain(toolchains.PROTO_TOOLCHAIN),
)