ArtifactsService: Add CPE export functionality.

Add the CPE report export to the artifacts service.
Includes the report itself and the warnings as individual artifacts.

BUG=chromium:905037
TEST=run_tests, manually ran endpoint

Change-Id: I1dc5fe22f72528f01c485037ab8f31e07b556f33
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1709145
Tested-by: Alex Klein <saklein@chromium.org>
Commit-Queue: Alex Klein <saklein@chromium.org>
Reviewed-by: Andrew Lamb <andrewlamb@chromium.org>
Reviewed-by: David Burger <dburger@chromium.org>
diff --git a/api/controller/artifacts.py b/api/controller/artifacts.py
index 7b5fc5e..09799d5 100644
--- a/api/controller/artifacts.py
+++ b/api/controller/artifacts.py
@@ -416,3 +416,35 @@
 
   for file_name in results:
     output_proto.artifacts.add().path = file_name
+
+
+@validate.exists('output_dir')
+def ExportCpeReport(input_proto, output_proto, config):
+  """Export a CPE report.
+
+  Args:
+    input_proto (BundleRequest): The input proto.
+    output_proto (BundleResponse): The output proto.
+    config (api_config.ApiConfig): The API call config.
+  """
+  chroot = controller_util.ParseChroot(input_proto.chroot)
+  output_dir = input_proto.output_dir
+
+  if input_proto.build_target.name:
+    # Legacy handling - use the default sysroot path for the build target.
+    build_target = controller_util.ParseBuildTarget(input_proto.build_target)
+    sysroot = sysroot_lib.Sysroot(build_target.root)
+  elif input_proto.sysroot.path:
+    sysroot = sysroot_lib.Sysroot(input_proto.sysroot.path)
+  else:
+    # TODO(saklein): Switch to validate decorators once legacy handling can be
+    #   cleaned up.
+    cros_build_lib.Die('sysroot.path is required.')
+
+  if config.validate_only:
+    return controller.RETURN_CODE_VALID_INPUT
+
+  cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
+
+  output_proto.artifacts.add().path = cpe_result.report
+  output_proto.artifacts.add().path = cpe_result.warnings