# Copyright 2022 The Bazel Authors. All rights reserved.
#
# 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.
"""Helpers copied from http_file source to be reused here.
The implementation below is copied directly from Bazel's implementation of `http_archive`.
Accordingly, the return value of this function should be used identically as the `auth` parameter of `http_archive`.
Reference: https://github.com/bazelbuild/bazel/blob/6.3.2/tools/build_defs/repo/http.bzl#L109
The helpers were further modified to support module_ctx.
"""
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc", "read_user_netrc", "use_netrc")
# Copied from https://sourcegraph.com/github.com/bazelbuild/bazel@26c6add3f9809611ad3795bce1e5c0fb37902902/-/blob/tools/build_defs/repo/http.bzl
_AUTH_PATTERN_DOC = """An optional dict mapping host names to custom authorization patterns.
If a URL's host name is present in this dict the value will be used as a pattern when
generating the authorization header for the http request. This enables the use of custom
authorization schemes used in a lot of common cloud storage providers.
The pattern currently supports 2 tokens: <login>
and
<password>
, which are replaced with their equivalent value
in the netrc file for the same host name. After formatting, the result is set
as the value for the Authorization
field of the HTTP request.
Example attribute and netrc for a http download to an oauth2 enabled API using a bearer token:
auth_patterns = { "storage.cloudprovider.com": "Bearer <password>" }netrc:
machine storage.cloudprovider.com password RANDOM-TOKENThe final HTTP request would have the following header:
Authorization: Bearer RANDOM-TOKEN""" # AUTH_ATTRS are used within whl_library and pip bzlmod extension. AUTH_ATTRS = { "auth_patterns": attr.string_dict( doc = _AUTH_PATTERN_DOC, ), "netrc": attr.string( doc = "Location of the .netrc file to use for authentication", ), } def get_auth(ctx, urls, ctx_attr = None): """Utility for retrieving netrc-based authentication parameters for repository download rules used in python_repository. Args: ctx(repository_ctx or module_ctx): The extension module_ctx or repository rule's repository_ctx object. urls: A list of URLs from which assets will be downloaded. ctx_attr(struct): The attributes to get the netrc from. When ctx is repository_ctx, then we will attempt to use repository_ctx.attr if this is not specified, otherwise we will use the specified field. The module_ctx attributes are located in the tag classes so it cannot be retrieved from the context. Returns: dict: A map of authentication parameters by URL. """ # module_ctx does not have attributes, as they are stored in tag classes. Whilst # the correct behaviour should be to pass the `attr` to the ctx_attr = ctx_attr or getattr(ctx, "attr", None) ctx_attr = struct( netrc = getattr(ctx_attr, "netrc", None), auth_patterns = getattr(ctx_attr, "auth_patterns", ""), ) if ctx_attr.netrc: netrc = read_netrc(ctx, ctx_attr.netrc) elif "NETRC" in ctx.os.environ: # This can be used on newer bazel versions if hasattr(ctx, "getenv"): netrc = read_netrc(ctx, ctx.getenv("NETRC")) else: netrc = read_netrc(ctx, ctx.os.environ["NETRC"]) else: netrc = read_user_netrc(ctx) return use_netrc(netrc, urls, ctx_attr.auth_patterns)