diff --git a/lib/fetchers.nix b/lib/fetchers.nix index dc6d8f137cb3..c09dbc799103 100644 --- a/lib/fetchers.nix +++ b/lib/fetchers.nix @@ -193,8 +193,8 @@ rec { }: fetcher: let - inherit (lib.attrsets) genAttrs intersectAttrs removeAttrs; - inherit (lib.trivial) const functionArgs setFunctionArgs; + inherit (lib.attrsets) intersectAttrs removeAttrs; + inherit (lib.trivial) functionArgs setFunctionArgs; inherit (commonH hashTypes) hashSet; fArgs = functionArgs fetcher; diff --git a/pkgs/by-name/ma/maven/build-maven-package.nix b/pkgs/by-name/ma/maven/build-maven-package.nix index 0df9aaf66046..c6ce59179f51 100644 --- a/pkgs/by-name/ma/maven/build-maven-package.nix +++ b/pkgs/by-name/ma/maven/build-maven-package.nix @@ -3,6 +3,7 @@ stdenv, jdk, maven, + writers, }: { @@ -28,6 +29,9 @@ let mvnSkipTests = lib.optionalString (!doCheck) "-DskipTests"; + + writeProxySettings = writers.writePython3 "write-proxy-settings" { } ./maven-proxy.py; + fetchedMavenDeps = stdenv.mkDerivation ( { name = "${pname}-${version}-maven-deps"; @@ -39,17 +43,36 @@ let JAVA_HOME = mvnJdk; + impureEnvVars = lib.fetchers.proxyImpureEnvVars; + buildPhase = '' runHook preBuild + + MAVEN_EXTRA_ARGS="" + + # handle proxy + if [[ -n "''${HTTP_PROXY-}" ]] || [[ -n "''${HTTPS_PROXY-}" ]] || [[ -n "''${NO_PROXY-}" ]];then + mvnSettingsFile="$(mktemp -d)/settings.xml" + ${writeProxySettings} $mvnSettingsFile + MAVEN_EXTRA_ARGS="-s=$mvnSettingsFile" + fi + + # handle cacert by populating a trust store on the fly + if [[ -n "''${NIX_SSL_CERT_FILE-}" ]] && [[ "''${NIX_SSL_CERT_FILE-}" != "/no-cert-file.crt" ]];then + keyStoreFile="$(mktemp -d)/keystore" + keyStorePwd="$(head -c10 /dev/random | base32)" + echo y | ${jdk}/bin/keytool -importcert -file "$NIX_SSL_CERT_FILE" -alias alias -keystore "$keyStoreFile" -storepass "$keyStorePwd" + MAVEN_EXTRA_ARGS="$MAVEN_EXTRA_ARGS -Djavax.net.ssl.trustStore=$keyStoreFile -Djavax.net.ssl.trustStorePassword=$keyStorePwd" + fi '' + lib.optionalString buildOffline '' - mvn de.qaware.maven:go-offline-maven-plugin:1.2.8:resolve-dependencies -Dmaven.repo.local=$out/.m2 ${mvnDepsParameters} + mvn $MAVEN_EXTRA_ARGS de.qaware.maven:go-offline-maven-plugin:1.2.8:resolve-dependencies -Dmaven.repo.local=$out/.m2 ${mvnDepsParameters} for artifactId in ${builtins.toString manualMvnArtifacts} do echo "downloading manual $artifactId" - mvn dependency:get -Dartifact="$artifactId" -Dmaven.repo.local=$out/.m2 + mvn $MAVEN_EXTRA_ARGS dependency:get -Dartifact="$artifactId" -Dmaven.repo.local=$out/.m2 done for artifactId in ${builtins.toString manualMvnSources} @@ -57,11 +80,11 @@ let group=$(echo $artifactId | cut -d':' -f1) artifact=$(echo $artifactId | cut -d':' -f2) echo "downloading manual sources $artifactId" - mvn dependency:sources -DincludeGroupIds="$group" -DincludeArtifactIds="$artifact" -Dmaven.repo.local=$out/.m2 + mvn $MAVEN_EXTRA_ARGS dependency:sources -DincludeGroupIds="$group" -DincludeArtifactIds="$artifact" -Dmaven.repo.local=$out/.m2 done '' + lib.optionalString (!buildOffline) '' - mvn package -Dmaven.repo.local=$out/.m2 ${mvnSkipTests} ${mvnParameters} + mvn $MAVEN_EXTRA_ARGS package -Dmaven.repo.local=$out/.m2 ${mvnSkipTests} ${mvnParameters} '' + '' runHook postBuild diff --git a/pkgs/by-name/ma/maven/maven-proxy.py b/pkgs/by-name/ma/maven/maven-proxy.py new file mode 100644 index 000000000000..7be8f1e3a705 --- /dev/null +++ b/pkgs/by-name/ma/maven/maven-proxy.py @@ -0,0 +1,86 @@ +""" +Maven doesn't honor HTTP[S]_PROXY and NO_PROXY env vars out of the box. +Instead, it expects the user to configure a settings.xml file. +We however impurely pass only these env vars in FODs. +This creates the XML file on demand, if one or more env vars is set. +""" + +import os +import sys +from urllib.parse import urlparse + + +def parse_proxy_url(url): + if url is None: + return None + parsed = urlparse(url) + + if parsed.hostname is None: + print(f"Failed to parse proxy URL {url}, ignoring", file=sys.stderr) + return None + + return { + 'protocol': parsed.scheme or 'http', + 'host': parsed.hostname, + 'port': parsed.port or (443 if parsed.scheme == 'https' else 80), + 'username': parsed.username, + 'password': parsed.password + } + + +def format_proxy_block(proxy, id_suffix, non_proxy_hosts): + auth = "" + if proxy.get("username"): + auth += f" {proxy['username']}\n" + if proxy.get("password"): + auth += f" {proxy['password']}\n" + + np_hosts = "" + if non_proxy_hosts: + np_hosts = f" {non_proxy_hosts}\n" + + return f""" + {id_suffix}-proxy + true + {proxy['protocol']} + {proxy['host']} + {proxy['port']} +{auth}{np_hosts} """ + + +def main(output_path): + http_proxy = parse_proxy_url(os.environ.get("HTTP_PROXY")) + https_proxy = parse_proxy_url(os.environ.get("HTTPS_PROXY")) + non_proxy_hosts = os.environ.get("NO_PROXY", "").replace(",", "|") + + proxy_blocks = [] + + if http_proxy: + proxy_blocks.append( + format_proxy_block(http_proxy, "http", non_proxy_hosts) + ) + if https_proxy and https_proxy != http_proxy: + proxy_blocks.append( + format_proxy_block(https_proxy, "https", non_proxy_hosts) + ) + + settings_xml = f""" + + +{'\n'.join(proxy_blocks)} + + +""" + + with open(output_path, "w") as f: + f.write(settings_xml) + + print(f"Generated Maven settings.xml at {output_path}") + + +if __name__ == "__main__": + output_file = sys.argv[1] if len(sys.argv) > 1 else "settings.xml" + main(output_file)