blob: c26562b871721f612f63a740177909a273441154 [file] [log] [blame]
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
AndroidAppCertificateInfo = provider(
"Info needed for Android app certificates",
fields = {
"pem": "Certificate .pem file",
"pk8": "Certificate .pk8 file",
"key_name": "Key name",
},
)
NoAndroidAppCertificateInfo = provider(
"A provider that indicates this target is NOT an android app certificate. It's used as the default value for an apex's certificate override.",
)
def _no_android_app_certificate_rule_impl(_ctx):
return [NoAndroidAppCertificateInfo()]
no_android_app_certificate = rule(
implementation = _no_android_app_certificate_rule_impl,
)
def _android_app_certificate_rule_impl(ctx):
cert_name = ctx.attr.certificate
pk8 = ctx.file.pk8
pem = ctx.file.pem
return [
AndroidAppCertificateInfo(pem = pem, pk8 = pk8, key_name = cert_name),
]
_android_app_certificate = rule(
implementation = _android_app_certificate_rule_impl,
attrs = {
"pem": attr.label(mandatory = True, allow_single_file = [".pem"]),
"pk8": attr.label(mandatory = True, allow_single_file = [".pk8"]),
"certificate": attr.string(mandatory = True),
},
)
def android_app_certificate(
name,
certificate,
**kwargs):
"Bazel macro to correspond with the Android app certificate Soong module."
_android_app_certificate(
name = name,
pem = certificate + ".x509.pem",
pk8 = certificate + ".pk8",
certificate = certificate,
**kwargs
)
def _search_cert_files(cert_name, cert_filegroup):
pk8 = None
pem = None
files = cert_filegroup[DefaultInfo].files.to_list()
# For overriding to a specific *file* in a provided directory with cert_name in the actual filename
for f in files:
if f.basename == cert_name + ".pk8":
pk8 = f
elif f.basename == cert_name + ".x509.pem":
pem = f
if not pk8:
fail("Could not find .pk8 file for the module '%s' in the list: %s" % (cert_name, files))
if not pem:
fail("Could not find .x509.pem file for the module '%s' in the list: %s" % (cert_name, files))
return pk8, pem
default_cert_directory = "build/make/target/product/security"
def _android_app_certificate_with_default_cert_impl(ctx):
product_var_cert = ctx.attr._default_app_certificate[BuildSettingInfo].value
cert_name = ctx.attr.cert_name
if cert_name and product_var_cert:
cert_dir = paths.dirname(product_var_cert)
elif cert_name:
cert_dir = default_cert_directory
elif product_var_cert:
cert_name = paths.basename(product_var_cert)
cert_dir = paths.dirname(product_var_cert)
else:
cert_name = "testkey"
cert_dir = default_cert_directory
if cert_dir != default_cert_directory:
filegroup_to_search = ctx.attr._default_app_certificate_filegroup
else:
filegroup_to_search = ctx.attr._hardcoded_certs
pk8, pem = _search_cert_files(cert_name, filegroup_to_search)
return [
AndroidAppCertificateInfo(
pk8 = pk8,
pem = pem,
key_name = "//" + cert_dir + ":" + cert_name,
),
]
android_app_certificate_with_default_cert = rule(
doc = """
This rule is the equivalent of an android_app_certificate, but uses the
certificate with the given name from a certain folder, or the default
certificate.
Modules can give a simple name of a certificate instead of a full label to
an android_app_certificate. This certificate will be looked for either in
the package determined by the DefaultAppCertificate product config variable,
or the hardcoded default directory. (build/make/target/product/security)
If a name is not given, it will fall back to using the certificate termined
by DefaultAppCertificate. (DefaultAppCertificate can function as both the
default certificate to use if none is specified, and the folder to look for
certificates in)
If neither the name nor DefaultAppCertificate is given,
build/make/target/product/security/testkey.{pem,pk8} will be used.
Since this rule is intended to be used from other macros, it's common to have
multiple android_app_certificate targets pointing to the same pem/pk8 files.
""",
implementation = _android_app_certificate_with_default_cert_impl,
attrs = {
"cert_name": attr.string(),
"_default_app_certificate": attr.label(
default = "//build/bazel/product_config:default_app_certificate",
),
"_default_app_certificate_filegroup": attr.label(
default = "//build/bazel/product_config:default_app_certificate_filegroup",
),
"_hardcoded_certs": attr.label(
default = "//build/make/target/product/security:android_certificate_directory",
),
"_apex_name": attr.label(
default = "//build/bazel/rules/apex:apex_name",
doc = "Name of apex this certificate signs.",
),
},
)