diff --git a/README.md b/README.md index 4feea480d..d0ec11c10 100644 --- a/README.md +++ b/README.md @@ -1058,6 +1058,19 @@ build --repo_env=JDK_JAVA_OPTIONS=-Djavax.net.ssl.trustStore= ``` can be added to your .bazelrc file if you need to specify custom cacerts for artifact resolution. +If you are using Bzlmod, you can also set truststore-related JVM options directly on `maven.install`: + +```python +maven.install( + # ... + truststore = "//path/to:cacerts", + truststore_password = "//path/to:truststore_password", # file contains the password + truststore_type = "PKCS12", +) +``` + +If `JDK_JAVA_OPTIONS` is set, it takes precedence over the `truststore*` settings. + ### Provide JVM options for Coursier with `COURSIER_OPTS` You can set up `COURSIER_OPTS` environment variable to provide some additional JVM options for Coursier. diff --git a/private/extensions/maven.bzl b/private/extensions/maven.bzl index 3478d550e..12cd760e8 100644 --- a/private/extensions/maven.bzl +++ b/private/extensions/maven.bzl @@ -75,6 +75,9 @@ install = tag_class( # Configuration "stuff" "additional_netrc_lines": attr.string_list(doc = "Additional lines prepended to the netrc file used by `http_file` (with `maven_install_json` only).", default = []), + "truststore": attr.label(allow_single_file = True, doc = "Optional Java truststore file to use for Maven resolution."), + "truststore_password": attr.label(allow_single_file = True, doc = "Optional Java truststore password file for Maven resolution."), + "truststore_type": attr.string(doc = "Optional Java truststore type (for example, JKS or PKCS12) for Maven resolution."), "use_credentials_from_home_netrc_file": attr.bool(doc = "Whether to pass machine login credentials from the ~/.netrc file to coursier.", default = False), "duplicate_version_warning": attr.string( doc = """What to do if there are duplicate artifacts @@ -471,6 +474,25 @@ def _process_module_tags(mctx): [None, "warn"], ) + repo["truststore"] = _fail_if_different( + "truststore", + repo.get("truststore"), + install.truststore, + [None], + ) + repo["truststore_password"] = _fail_if_different( + "truststore_password", + repo.get("truststore_password"), + install.truststore_password, + [None], + ) + repo["truststore_type"] = _fail_if_different( + "truststore_type", + repo.get("truststore_type"), + install.truststore_type, + [None, ""], + ) + # Get the longest timeout timeout = repo.get("resolve_timeout", install.resolve_timeout) if install.resolve_timeout > timeout: @@ -666,6 +688,9 @@ def maven_impl(mctx): repo["fetch_javadoc"] = install.fetch_javadoc repo["fetch_sources"] = install.fetch_sources repo["resolver"] = install.resolver + repo["truststore"] = install.truststore + repo["truststore_password"] = install.truststore_password + repo["truststore_type"] = install.truststore_type repo["strict_visibility"] = install.strict_visibility if len(install.repositories): mapped_repos = [] @@ -727,6 +752,9 @@ def maven_impl(mctx): use_credentials_from_home_netrc_file = repo.get("use_credentials_from_home_netrc_file"), maven_install_json = repo.get("lock_file"), dependency_index = repo.get("dependency_index"), + truststore = repo.get("truststore"), + truststore_password = repo.get("truststore_password"), + truststore_type = repo.get("truststore_type"), resolve_timeout = repo.get("resolve_timeout"), use_starlark_android_rules = repo.get("use_starlark_android_rules"), aar_import_bzl_label = repo.get("aar_import_bzl_label"), @@ -787,6 +815,9 @@ def maven_impl(mctx): generate_compat_repositories = False, maven_install_json = repo.get("lock_file"), dependency_index = repo.get("dependency_index"), + truststore = repo.get("truststore"), + truststore_password = repo.get("truststore_password"), + truststore_type = repo.get("truststore_type"), override_targets = overrides.get(name), override_target_visibilities = override_visibilities.get(name, {}), strict_visibility = repo.get("strict_visibility"), diff --git a/private/rules/coursier.bzl b/private/rules/coursier.bzl index 762da0971..cfda5433c 100644 --- a/private/rules/coursier.bzl +++ b/private/rules/coursier.bzl @@ -158,6 +158,31 @@ def _is_file(repository_ctx, path): def _is_directory(repository_ctx, path): return repository_ctx.which("test") and repository_ctx.execute(["test", "-d", path]).return_code == 0 +def _jdk_java_options(repository_ctx): + jdk_java_options = repository_ctx.os.environ.get("JDK_JAVA_OPTIONS") + if jdk_java_options: + return jdk_java_options + truststore = repository_ctx.attr.truststore + if not truststore: + return None + truststore_path = repository_ctx.path(truststore) + if not _is_file(repository_ctx, str(truststore_path)): + return None + jvm_flags = [ + "-Djavax.net.ssl.trustStore=" + str(truststore_path), + ] + truststore_password = repository_ctx.attr.truststore_password + if truststore_password: + truststore_password_path = repository_ctx.path(truststore_password) + if _is_file(repository_ctx, str(truststore_password_path)): + truststore_password_value = repository_ctx.read(str(truststore_password_path)).strip() + if truststore_password_value: + jvm_flags.append("-Djavax.net.ssl.trustStorePassword=" + truststore_password_value) + truststore_type = repository_ctx.attr.truststore_type + if truststore_type: + jvm_flags.append("-Djavax.net.ssl.trustStoreType=" + truststore_type) + return " ".join(jvm_flags) + def _is_unpinned(repository_ctx): return repository_ctx.attr.pinned_repo_name != "" @@ -852,7 +877,7 @@ def generate_pin_target(repository_ctx, unpinned_pin_target): boms = repr(repository_ctx.attr.boms), artifacts = repr(repository_ctx.attr.artifacts), excluded_artifacts = repr(repository_ctx.attr.excluded_artifacts), - jvm_flags = repr(repository_ctx.os.environ.get("JDK_JAVA_OPTIONS")), + jvm_flags = repr(_jdk_java_options(repository_ctx)), repos = repr(repository_ctx.attr.repositories), fetch_sources = repr(repository_ctx.attr.fetch_sources), fetch_javadocs = repr(repository_ctx.attr.fetch_javadoc), @@ -1065,6 +1090,10 @@ def make_coursier_dep_tree( # https://github.com/coursier/coursier/blob/1cbbf39b88ee88944a8d892789680cdb15be4714/modules/paths/src/main/java/coursier/paths/CoursierPaths.java#L29-L56 environment = {"COURSIER_CACHE": str(repository_ctx.path(coursier_cache_location))} + jdk_java_options = _jdk_java_options(repository_ctx) + if jdk_java_options: + environment["JDK_JAVA_OPTIONS"] = jdk_java_options + cmd.extend(additional_coursier_options) # Use an argsfile to avoid command line length limits, requires Java version > 8 @@ -1591,6 +1620,9 @@ pinned_coursier_fetch = repository_rule( "generate_compat_repositories": attr.bool(default = False), # generate a compatible layer with repositories for each artifact "maven_install_json": attr.label(allow_single_file = True), "dependency_index": attr.label(allow_single_file = True), + "truststore": attr.label(allow_single_file = True), + "truststore_password": attr.label(allow_single_file = True), + "truststore_type": attr.string(), "override_targets": attr.string_dict(default = {}), "override_target_visibilities": attr.string_list_dict(default = {}), "strict_visibility": attr.bool( @@ -1663,6 +1695,9 @@ coursier_fetch = repository_rule( ), "maven_install_json": attr.label(allow_single_file = True), "dependency_index": attr.label(allow_single_file = True), + "truststore": attr.label(allow_single_file = True), + "truststore_password": attr.label(allow_single_file = True), + "truststore_type": attr.string(), "override_targets": attr.string_dict(default = {}), "override_target_visibilities": attr.string_list_dict(default = {}), "strict_visibility": attr.bool(