[assembly] Establish contract for base-resolver config verifier

This change implements a simple golden file check for the new
base-resolver structured configuration. It includes a custom
implementation to deal with the need to have separate goldens for
"eng" and "non-eng" build types, and vacuously integrates the
implementation into assembly. The integration is vacuous because
it always compares a golden file to itself with TODOs in the
assembly build files to add the correct file paths when the
base-resolver structured configuration lands in fxrev.dev/687102.

Bug: 102968
Change-Id: I4bb1ef25209e9057782f45ae8643270e598737e8
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/694083
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Reviewed-by: Aaron Wood <aaronwood@google.com>
Reviewed-by: Allison Pearce <ampearce@google.com>
Fuchsia-Auto-Submit: Mark Dittmer <markdittmer@google.com>
diff --git a/build/images/fuchsia/BUILD.gn b/build/images/fuchsia/BUILD.gn
index 7b48766..720e40e 100644
--- a/build/images/fuchsia/BUILD.gn
+++ b/build/images/fuchsia/BUILD.gn
@@ -102,6 +102,9 @@
     # pass that to the assembled_system() call(s).
     if (fuchsia_product_assembly_config_file != false) {
       product_assembly_config_file = fuchsia_product_assembly_config_file
+    } else {
+      product_assembly_config_file =
+          "//build/assembly/empty_product_config.json"
     }
     if (fuchsia_product_assembly_config_label != false) {
       product_assembly_config_dep = fuchsia_product_assembly_config_label
@@ -289,7 +292,7 @@
     if (include_fvm_blob_sparse) {
       public_deps += [ ":copy_fvm_blob_sparse" ]
     }
-    deps = []
+    deps = [ ":verify_base_resolver_config" ]
     if (!is_coverage && custom_signing_script == "") {
       deps += [
         ":verify_capability_routes",
@@ -571,11 +574,7 @@
       ":partitions_config",
     ]
 
-    if (fuchsia_product_assembly_config_file != false) {
-      product_config = fuchsia_product_assembly_config_file
-    } else {
-      product_config = "//build/assembly/empty_product_config.json"
-    }
+    product_config = fuchsia_base.product_assembly_config_file
     if (fuchsia_product_assembly_config_label != false) {
       deps += [ fuchsia_product_assembly_config_label ]
     }
@@ -662,6 +661,71 @@
   # Scrutiny verifiers
   ##################################################
 
+  # TODO(fxbug.dev/102968): There is a need for scrutiny verifiers that process
+  # structured configuration files. Until such verifiers are ready, structured
+  # configuration files for sensitive components are verified using the
+  # strategy below.
+  action("verify_base_resolver_config") {
+    # TODO(fxbug.dev/102968): Uncomment in upcoming fxrev.dev/687102.
+    # _cvf_eng_golden =
+    #     "//src/security/policy/build/base_resolver_golden_eng.cvf"
+
+    _cvf_non_eng_golden =
+        "//src/security/policy/build/base_resolver_golden_non_eng.cvf"
+
+    # Follow output conventions defined by cvf template in
+    # //tools/configc/build/config.gni.
+    # TODO(fxbug.dev/102968): Uncomment in upcoming fxrev.dev/687102.
+    # _cvf_target = "//src/sys/base-resolver:values_from_gn"
+    # _cvf_output_name = "values_from_gn"
+    # _cvf_out_dir = get_label_info(_cvf_target, "target_out_dir")
+    # _cvf_output = "${_cvf_out_dir}/${_cvf_output_name}.cvf"
+
+    _output = "${target_out_dir}/${target_name}.verified"
+
+    script = "//src/security/policy/build/verify_golden_by_build_type.py"
+    args = [
+      "--eng-golden",
+
+      # TODO(fxbug.dev/102968): Uncomment/swap in upcoming fxrev.dev/687102.
+      # rebase_path(_cvf_eng_golden, root_out_dir),
+      rebase_path(_cvf_non_eng_golden, root_out_dir),
+
+      "--non-eng-golden",
+      rebase_path(_cvf_non_eng_golden, root_out_dir),
+
+      "--product-config",
+      rebase_path(fuchsia_base.product_assembly_config_file, root_out_dir),
+
+      "--input",
+
+      # TODO(fxbug.dev/102968): Uncomment/swap in upcoming fxrev.dev/687102.
+      # rebase_path(_cvf_output, root_out_dir),
+      rebase_path(_cvf_non_eng_golden, root_out_dir),
+
+      "--output",
+      rebase_path(_output, root_out_dir),
+    ]
+
+    inputs = [
+      # TODO(fxbug.dev/102968): Uncomment in upcoming fxrev.dev/687102.
+      # _cvf_eng_golden,
+      # _cvf_output,
+
+      _cvf_non_eng_golden,
+      fuchsia_base.product_assembly_config_file,
+    ]
+    outputs = [ _output ]
+
+    deps = [
+      # TODO(fxbug.dev/102968): Uncomment in upcoming fxrev.dev/687102.
+      # _cvf_target,
+    ]
+    if (defined(fuchsia_base.product_assembly_config_dep)) {
+      deps += [ fuchsia_base.product_assembly_config_dep ]
+    }
+  }
+
   # See //build/scrutiny/verifier/verify_*.gni and //build/security.gni for
   # documentation.
 
diff --git a/src/security/policy/build/base_resolver_golden_eng.cvf b/src/security/policy/build/base_resolver_golden_eng.cvf
new file mode 100644
index 0000000..c6fd4c9
--- /dev/null
+++ b/src/security/policy/build/base_resolver_golden_eng.cvf
Binary files differ
diff --git a/src/security/policy/build/base_resolver_golden_non_eng.cvf b/src/security/policy/build/base_resolver_golden_non_eng.cvf
new file mode 100644
index 0000000..c6fd4c9
--- /dev/null
+++ b/src/security/policy/build/base_resolver_golden_non_eng.cvf
Binary files differ
diff --git a/src/security/policy/build/verify_golden_by_build_type.py b/src/security/policy/build/verify_golden_by_build_type.py
new file mode 100644
index 0000000..db5218c
--- /dev/null
+++ b/src/security/policy/build/verify_golden_by_build_type.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3.8
+
+# Copyright 2022 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import filecmp
+import json
+import sys
+
+from pathlib import Path
+
+
+def main():
+    params = argparse.ArgumentParser(
+        description=
+        "Verify file against golden with different goldens for eng and non-eng build types"
+    )
+    params.add_argument("--eng-golden", type=Path, required=True)
+    params.add_argument("--non-eng-golden", type=Path, required=True)
+    params.add_argument("--product-config", type=Path, required=True)
+    params.add_argument("--input", type=Path, required=True)
+    params.add_argument("--output", type=Path, required=True)
+    args = params.parse_args()
+
+    with open(args.product_config, 'r') as product_config:
+        product_config_json = json.load(product_config)
+        build_type = product_config_json['platform']['build_type']
+        if build_type == 'eng':
+            golden = args.eng_golden
+        else:
+            golden = args.non_eng_golden
+        if not filecmp.cmp(golden, args.input, shallow=False):
+            raise Exception(
+                'Golden and input files differ:\ngolden={}\ninput={}'.format(
+                    golden, args.input))
+
+    args.output.touch()
+
+
+if __name__ == "__main__":
+    sys.exit(main())