rules_jvm_external icon indicating copy to clipboard operation
rules_jvm_external copied to clipboard

Failed to get artifact from private repo when using URL basic auth

Open geoffliu opened this issue 3 years ago • 3 comments

Hi all, I have artifacts hosted on a private repository using jfrog. In my workspace file, I have a maven_install rule with

artifacts = [
  'com.functorz:ztype:0.3.19',
],
repositories = [
  "https://repo1.maven.org/maven2",
  "https://geoff%40functorz.com:<password>@functorz.jfrog.io/artifactory/maven",
]

and in a build rule, I have a dependency on @maven//:com_functorz_ztype. Running bazel build yields the following error:

Resolution error: Error downloading com.functorz:ztype:0.3.19
  not found: https://repo1.maven.org/maven2/com/functorz/ztype/0.3.19/ztype-0.3.19.pom
  forbidden: https://functorz.jfrog.io/artifactory/maven/com/functorz/ztype/0.3.19/ztype-0.3.19.pom

Some observations:

  • Trying it with curl for https://geoff%40functorz.com:<password>@functorz.jfrog.io/artifactory/maven/com/functorz/ztype/0.3.19/ztype-0.3.19.pom returns the pom file successfully
  • Using a credentials file via COURSIER_CREDENTIALS works as well

My best guess at the moment is that both my username (email) and password have special characters in them. I used url encoded versions of them in the URL, which works fine for curl. Is it possible that in the interactions between Bazel and Coursier, this case isn't handled properly?

Anyway, just a guess. Happy to help debug and provide more info if needed.

geoffliu avatar Jan 22 '22 17:01 geoffliu

OK, I did a bit more digging, here are some more notes in no particular order:

  • When passing repositories as an object (i.e. { repo_url: ..., user: ..., password: ... }), the --credentials flag passed to java args file is broken. The host user:pass string is not properly quoted to handle the space, and Coursier will choke up. (This could probably be a separate issue on its own)
  • Passing a URL encoded username or password as part of the URL to Coursier is not decoded and results in a "forbidden"
  • Passing unencoded username or password with an @ in it causes Coursier to mistake the @ as the start of the host. Interestingly, the Bazel scripts handles this case by doing an rsplit(@, 1)

At the moment, the only workaround is to pass a credentials file using an environment variable.

geoffliu avatar Jan 25 '22 05:01 geoffliu

When downloading (and assuming pinning), Bazel should be using your .netrc file for authentication. When pinning (or not using pinned downloads), you're likely correct.

For now, (as you say) I would strongly recommend using the COURSIER_CREDENTIALS environment variable.

Just in case someone stumbles on this issue while looking for how to solve this problem, I'll detail the required steps here.

First, create a ~/.config/coursier/credentials.properties file which should contain your authentication credentials.

maven.username= maven.password=<your API key> maven.host=your.maven.repo.com maven.realm=Maven Realm maven.auto=true

Secondly, export this the absolute path to this file as COUSIER_CREDENTIALS via your shell's rc file (eg. .bashrc or .zshrc). Start a new shell or export the env var manually if you don't want to start a new shell session.

I know that a workaround is far from ideal, but while we're finding the time to address this issue, I hope this solution is okay.

If finding a better solution is urgent for you, and you'd like to send a PR to address any (all? :) ) of these problems, I'd be very happy to review it.

shs96c avatar Feb 18 '22 13:02 shs96c

@shs96c think you have a typo in the env var missing an R, coursier vs cousier.

Side question does this invalidate how the DAG is calculated and invalidate remote caches if the auth is different?

nfisher avatar Sep 14 '22 21:09 nfisher