Gradle fails to download artifacts from Nexus maven repository - 401 Authorization required - maven

I've configured gradle build to use our company's nexus repo but maven does not seem to be able to authorized correctly - I keep getting erros such as
Failed to get resource: HEAD. [HTTP HTTP/1.1 401 Authorization Required: https://maven.gooddata.com/nexus/content/repositories/gooddata/org/codehaus/groovy/groovy-all/2.0.4/groovy-all-2.0.4.pom]
Strangely enough, the deploying to the same nexus repo (via mavenDeployer) is working seamlessly.
Below is part of my build script related to the maven repo configuration (maven_user and maven_password are defined in ~/.gradle/gradle.properties).
apply plugin: 'maven'
ext {
repos = [
my : "<my_repo_url>",
my_snapshot : "<my_snapshots_repo_url>"
]
}
repositories {
mavenLocal()
maven {
url repos.my
credentials {
username = maven_user
password = maven_password
}
}
maven {
url repos.my_snapshot
credentials {
userName = maven_user
password = maven_password
}
}
mavenCentral()
maven { url "http://repository.codehaus.org/" }
maven { url "http://sardine.googlecode.com/svn/maven" }
maven { url "http://snapshots.repository.codehaus.org" }
}
uploadArchives {
repositories.mavenDeployer {
repository(url : repos.my) {
authentication(userName : maven_user, password : maven_password)
}
snapshotRepository(url : repos.my_snapshot) {
authentication(userName : maven_user, password : maven_password)
}
}
}
Any suggestions what's going on?

Your username property is capitalized wrongly and you should leave out the '=' sign with the username and password setting. Changing your repository definition to the following should solve your problems:
maven {
url repos.my
credentials {
username maven_user
password maven_password
}
}

Thread is a bit old now, but just wanted to highlight a gotcha I had when following the above .. my admin had created a password with both a single and double quote in, which resulted in a similar 401

Related

gradle can't resolve dependency in privare repository (nexus)

I am running into problems with gradle while resolving dependencies. Some of my projects uses a core-lib which I provide by my private repository - nexus3. And the weirdest part is, one of this projects resolves the dependency, while the others can't. I have no Idea what I am doing wrong:
This is how I define my gradle repositories:
repositories {
maven {
credentials {
username = "user"
password = "password"
}
url = uri("https://my-nexus-url/repository/group-repo/")
}
mavenCentral()
}
This is how the dependency is implemented:
dependencies {
...
implementation("my.lib.core:core:1.0")
...
}
This is how is the puiblishing configure block:
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "my.lib.core"
artifactId = "core"
version = "1.0"
from(components["java"])
}
}
repositories {
maven {
credentials {
username = "user"
password = "password"
}
url = uri("https://my-nexus-url/repository/release-repo/")
}
}
}
I am also able to download the artifact via nexus web ui and curl. Furthermore already one of these projects is able to implement it. The rest of them throws:
Could not resolve my.lib.core:core:1.0.
Required by:
project :lib
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
Running gradlew ass --refresh-dependencies works fine and ends with:
Cached resource https://my-nexus-url/repository/group-repo/my/lib/core/core/1.0/core-1.0.jar is up-to-date (lastModified: Tue Mar 08 23:05:19 CET 2022).

How to provide credentials for global init.gradle pluginManagement for Gradle 5.6.2+?

After the recent security fixes in Gradle 5.6.2+, we're unable to use global plugin management in init.gradle script.
The section, which is described in the Gradle documentation does not provide any help about using Nexus server requiring authentication.
The workaround I've found is following: I had to manually hardcode credentials inside of the script even though the nexusUsername and nexusPassword is already defined in gradle.properties.
allprojects {
repositories {
mavenLocal()
maven {
url "https://nexus-repo-requiring-auth/"
credentials {
username nexusUsername
password nexusPassword
}
}
}
settingsEvaluated { settings ->
settings.pluginManagement.repositories {
//This is a workaround, because the global properties are not available here
def localNexusUsername = "nexusUser1"
def localNexusPassword = "nexusPass1"
maven {
url "https://nexus-repo-requiring-auth/"
credentials {
username localNexusUsername
password localNexusPassword
}
}
}
}
Is there a way, how to read global variables inside of the settingsEvaluated block? Or any other way to define the plugin repository?
It's not a solution, but a different work-around. I found that if I defined my plugin repositories in the settings.gradle file it was able to read the variables:
pluginManagement {
repositories {
maven {
authentication {
basic(BasicAuthentication)
}
url "https://artifactory.redacted.com/gradle-plugins-mirror/"
credentials {
username "$artifactory_user"
password "$artifactory_password"
}
}
}
}
This worked better for me as we add the ~/.gradle/init.gradle file for each user, so everyone uses the same internal mirors.

How do I replace a Maven repository with a local directory after it is defined in a Gradle build?

I'm trying to write tests for a build process, so my unit test wants to replace the actual repository locations with local locations to avoid poisoning the real server. (Plus, I suppose, the person running the test might not have access to publish anyway.)
In the build itself:
publishing {
repositories {
maven {
name = 'snapshot'
url = "${artifactory_contextUrl}/libs-snapshot-local"
credentials {
username artifactory_user
password artifactory_password
}
}
maven {
name = 'release'
url = "${artifactory_contextUrl}/libs-release-local"
credentials {
username artifactory_user
password artifactory_password
}
}
}
}
In my test build, I'm trying to override it with this:
publishing {
repositories {
getByName('snapshot') {
url = uri('/tmp/local-repo/snapshots')
}
getByName('release') {
url = uri('/tmp/local-repo/release')
}
}
}
When I try to run the build, I get:
Execution failed for task ':publishMavenJavaPublicationToReleaseRepository'.
> Failed to publish publication 'mavenJava' to repository 'release'
> Authentication scheme 'all'(Authentication) is not supported by protocol 'file'
There are a lot of posts out on the web about this specific error, but it always seems to be people who accidentally put a file path in when they should have put a URI. I'm putting in a URI deliberately, though, so is there a way to get this to work?
I have also tried this:
publishing {
repositories {
clear()
maven {
name = 'snapshot'
url = uri('/tmp/local-repo/snapshots')
}
maven {
name = 'release'
url = uri('/tmp/local-repo/release')
}
}
}
That fails with:
A problem occurred configuring root project 'test-common-plugin1913987501683151177'.
> Exception thrown while executing model rule: PublishingPluginRules#publishing(ExtensionContainer)
> Cannot add task 'publishMavenJavaPublicationToSnapshotRepository' as a task with that name already exists.
I was surprised that deleting all the repositories doesn't also delete all the tasks they own. When I try to programmatically delete the task it's complaining about, Gradle claims that it doesn't exist.
Alright, I ended up having to read the source of Gradle (again), but I found a way to do it. Essentially you can directly set credentials back to null, like this:
publishing {
repositories {
getByName('snapshot') {
url = uri('/tmp/local-repo/snapshots')
configuredCredentials = null
}
getByName('release') {
url = uri('/tmp/local-repo/release')
configuredCredentials = null
}
}
}

Can I add a custom repository to gradle.properties?

I'd like to be able to define a repository in settings (ideally user gradle.properties)
The end goal is something like this:
repositories {
mavenCentral() // Can't/don't want to use this
nexusCentral() // Can use these - on network Nexus server
nexusSnapshot()
}
How would I go about doing this? Again, this would go in the user-level gradle.properties file ideally, so we don't have to reference it in every single module.
This is just a plain maven style artifact repository provided by Maven, the manual way would be:
maven {
url "http://path/to/nexus"
}
One other requirement is the use of the "publish" task, which has credentials defined for a repository (that Jenkins uses to publish the module):
publishing {
...
maven {
url "http://path/to/nexus"
// Jenkins provides these as -P Gradle parameters.
credentials {
username = "${uploaderUser}"
password = "${uploaderPassword}"
}
}
These credentials would not be known to regular users, but would ideally be configured in Jenkin's gradle.properties. We wouldn't want users builds to fail because they can't resolve the credentials - they would never even use the "publish" task.
You can use somenthing like this:
maven {
credentials {
username getCredentialsMavenUsername()
password getCredentialsMavenPassword()
}
url 'xxxxx'
}
/**
* Returns the credential username used by Maven repository
* Set this value in your ~/.gradle/gradle.properties with CREDENTIALS_USERNAME key
* #return
*/
def getCredentialsMavenUsername() {
return hasProperty('CREDENTIALS_USERNAME') ? CREDENTIALS_USERNAME : ""
}
/**
* Returns the credential password used by Maven repository
* Set this value in your ~/.gradle/gradle.properties with CREDENTIALS_PASSWORD key
* #return
*/
def getCredentialsMavenPassword() {
return hasProperty('CREDENTIALS_PASSWORD') ? CREDENTIALS_PASSWORD : ""
}
If the user hasn't the credentials the script doesn't fail.
Not sure if that answers your question, but you can put this in the gradle.properties file:
nexusUrl=http://path/to/nexus
and do this in the build.gradle:
maven {
url project.property(nexusUrl)
}
EDIT:
regarding your credentials, all you should need is something like
if (project.hasProperty('uploaderUser') && project.hasProperty('uploaderPassword')) {
credentials {
username = project.property('uploaderUser')
password = project.property('uploaderPassword')
}
}
Solved this issue by replacing jcenter() in Project/andoird/build.gradle with maven { url 'http://nexusUrl' } under buildscript and allprojects:
buildscript {
repositories {
google()
maven { url 'http://nexusUrl' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}
allprojects {
repositories {
google()
maven { url 'http://nexusUrl' }
}
}
and in fluttersdk/packages/flutter_tools/gradle/flutter.gradle replaced jcenter with maven { url 'http://nexusUrl' } under buildscript:
buildscript {
repositories {
google()
maven { url 'nexusUrl' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}

Context URL cannot be empty - Artifactory Gradle Plugin

I'm trying to get to the Artifactory Gradle plugin working to publish to my local Artifactory instance.
I have the latest version (default install) running at localhost:8081/artifactory. I can verify this with access via a webbrowser.
However, with my bare minimum example .. I am getting a "Context URL cannot be found error
Note that I have specified all the mandatory required Artifactory configurations settings - (as indicated on the Artifactory Gradle WebPage) .. including the Context URL.
buildscript {
repositories{ maven { url 'http://repo.jfrog.org/artifactory/gradle-plugins' } }
dependencies{ classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.0.12'}
}
apply plugin: 'artifactory'
artifactory {
contextUrl = 'http://localhost:8081/artifactory' //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'integration-libs' //The Artifactory repository key to publish to
username = 'admin' //The publisher user name
password = 'password'
}
}
resolve {
repository {
repoKey = 'libs-releases' //The Artifactory (preferably virtual) repository key to resolve from
}
}
}
This looks like a weird bug and I'm not sure what causes it. I get it in some of my gradle build files but others seem to work fine.
I fixed it by defining the contextUrl again inside the publish element, so your script will now look like:
artifactory {
contextUrl = 'http://localhost:8081/artifactory' //The base Artifactory URL if not overridden by the publisher/resolver
publish {
contextUrl = 'http://localhost:8081/artifactory' // <- this is the fix
repository {
repoKey = 'integration-libs' //The Artifactory repository key to publish to
username = 'admin' //The publisher user name
password = 'password'
}
}
resolve {
repository {
repoKey = 'libs-releases' //The Artifactory (preferably virtual) repository key to resolve from
}
}
}
You might also have to define it again inside the resolve element.

Resources