Maven deployment user can deploy, but not read repository - maven

The last few days I was trying to set a maven-development environment up. We're using TeamCity for the CI, SonarQube for analysis and SonaType Nexus for the repository management.
TeamCity and SonarQube are working like a charm - The nexus however gives us lots of trouble.
This kind of set up is nothing special, I've done it several times now. This time however, I got a very weird bug: TeamCity is able to deploy artifacts to the nexus, but gives an org.apache.maven.wagon.authorization.AuthorizationException: Not authorized , ReasonPhrase:Unauthorized. error when reading dependencies from the nexus.
I even tried changing the user that TeamCity uses from deployment to admin, same issue. chown returned the correct values as well (owned by the "buildagent" user).
I seriously have no clue what could cause this issue, I already tried reinstalling the nexus 3 times, even added the admin role to the "deployment" user - no change whatsoever.
The settings.xml the "buildagent" user uses has the following content (passwords marked with XXX):
<servers>
<!-- This is the username password used to access the nexus repository -->
<server>
<id>central</id>
<username>deployment</username>
<password>XXX</password>
</server>
<server>
<id>rn-releases</id>
<username>deployment</username>
<password>XXX</password>
</server>
<server>
<id>rn-snapshots</id>
<username>deployment</username>
<password>XXX</password>
</server>
</servers>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>central</mirrorOf>
<url>http://build.example.com:8301/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
For your information: The build log from TeamCity states that the settings are getting read correctly as well, so that's not the cause either.
I really would like to fix this asap, since we have developers waiting to continue on their projects (and we don't want to give out the url if it's not secured, we have private projects running on the CI).
Thanks in advance!
Edit:
So I now even tried installing artifactory - and I still have the same issue. It seems to be something with either A: Maven or B:TeamCity.

The mirror to Nexus has the id nexus, but there's no <server>-entry with this id. If you add that to the settings.xml with the correct credentials, it should all work again.

Related

How to combine maven settings files

I've been added to another team at work. Both teams use their own Nexus servers, and have provided me their own settings files, so currently I have to do a lot of hoop-jumping to make sure I'm using the correct settings.xml file to get the projects to build. Is there a good way to merge these files? I've been going through the maven documentation but getting really confused. Settings files are below (identifying info removed)
Team 1 settings file
<settings>
<mirrors>
<mirror>
<id>Nexus</id>
<name>Company Nexus Public Mirror</name>
<url>http://build.company.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>snapshots</id>
<username>deployment</username>
<password>password1</password>
</server>
<server>
<id>releases</id>
<username>deployment</username>
<password>password2</password>
</server>
</servers>
<activeProfiles>
<activeProfile>jenkins</activeProfile>
</activeProfiles>
</settings>
Team 2 settings file
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://domain.company.com:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
<servers>
<server>
<id>snapshots</id>
<username>deployment</username>
<password>password3</password>
</server>
<server>
<id>releases</id>
<username>deployment</username>
<password>password4</password>
</server>
</servers>
</settings>
I tried just merging the <mirrors> sections so both mirrors were listed, but only one team's code builds. I also don't understand how the server id's work. I'll have different username/password combinations for the different servers. I'd think the server id should match the id in the mirrors sections, but that clearly isn't the case. But if not that, how would maven know which snapshots or releases server to use?
You have to check what settings are maven taking during the deployment of the artifacts by using this command:
mvn help:effective-settings
Sometimes it can happen that you are using local settings and global settings (taking first the provided by the maven installation and then the provided by the repository), but maven is not recognizing both. With this command, you can verify the actual settings maven is taking during the deployment. In addition, you can locate the actual file maven is taking and, as a consequence, modify the file properly (with vim, for example) according to the configuration needed by the server.
Remember that there are two locations where a settings.xml file may live:
Maven installation directory
$M2_HOME/conf/settings.xml
User-specific settings file
~/.m2/settings.xml
If both files exists, their contents gets merged, with the user-specific settings.xml being dominant. https://maven.apache.org/settings.html
In my experience there are really only one feasible and easy solution and it does NOT include merging the settings files.
Switch settings files whenever necessary. Just have both files somewhere and have a command line script that switches them (copying over top of settings.xml from a template file). Or alternatively .. have different commands that pass in -s .. problem with that is that you this does not integrate nicely with the IDE usage.
If the id values for the different servers use different names you could also install a Nexus Repository Manager locally on your machine and proxy the two external ones. But in your scenario that wont work since overlapping id values for different servers are used. That must stem from a misunderstanding on both teams on what the id is used for.
If you want to merge several settings file into one, you can (should) use XInclude. It is a W3C recommendation and the best solution for your case.
There is a great tutorial about the usage of Xinclude. Here is the link
I hope this helps.

How to use the internet for maven builds instead, if the corporate maven repository is offline or down?

I have a corporate repository defined in my POM:
<distributionManagement>
<repository>
<id>central</id>
<name>libs-release-local</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/libs-release-local</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>libs-snapshot-local</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/libs-snapshot-local</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
But they keep unplugging and moving or rebooting that box, so sometimes it's not available. Is there a way to tell my maven poms "try and use the corporate repository, but if it's down use the internet?" I tried specifying the repository and plugin repository outside of the distribution management section to no avail.
May anyone offer guidance please?
In settings.xml I have a mirror and a local repository defined:
<mirrors>
<mirror>
<mirrorOf>*</mirrorOf>
<name>repo</name>
<url>http://bi-pub.wgresorts.com:8081/artifactory/repo</url>
<id>repo</id>
</mirror>
</mirrors>
<localRepository>C:\apache-maven-3.1.1\.m2\repository</localRepository>
I don't want to have to keep changing the settings.xml depending on the whims of the IT department, can I set it up so it tries the corporate one goes to the internet if it's down?
EDIT
If you used the id central, you'll have to first create a pom with central that points to the real one on the internet before you can fix this. It can also point to your corporate repository but with a different ID. Then it will fall over to the internet if your corporate repository is down.
I think you may also have to delete the mirror section from the settings.xml
For better or worse, binary repository is a critical piece of the production pipeline.
You don't ask "what options do I have if my site is down", do you? You just keep your site up. Same story here, your IT department should realize that.
You can run Artifactory in DR mode (active/passive) or even in HA mode (active/active). Your repository has all the means to stay up 24/7, so you really don't need those workarounds.
First of all your settings.xml file is not correct.
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
You have to use the above definition to say maven to search for artifacts as well plugins into the mirror repository (doesn't matter if it's a nexus or artifactory).
As supplemental you have defined uniqueVersion which has no effect starting with Maven 3.
Apart from that the definition in setting.xml is for reading whereas the definition in pom.xml distributionManagement is used for writing which means deploying artifacts or the site.
So in both cases you need the repository up and working as already mentioned by JBaruch. If you IT department is not able to handle such cases (basic IT operations) i would hardly think about that.
Every build in your company depends on the availability of the Repository Manager either for downloading artifacts or for deploying results of the builds and for following steps of the pipeline as well.

Sonatype Nexus: How to set a single server credentials for multiple repositories in maven's settings.xml?

We have multiple repositories in Nexus (i.e., releases, snapshot and site). All 3 repos are under public group and users uses the same credentials to access all these repositories. Providing the same username and password in settings.xml for each repository makes it redundant and hard to maintain them.
Could you please suggest an elegant way to describe one server credential for all the 3 repositories?
Any help is greatly appreciated.
We are using maven 2.2.1 and Nexus OSS 2.7.1
Here is my settings.xml
<settings>
<servers>
<server>
<id>snapshot</id>
<username>deployment</username>
<password>deployment123</password>
</server>
<server>
<id>release</id>
<username>deployment</username>
<password>deployment123</password>
</server>
<server>
<id>site</id>
<username>deployment</username>
<password>deployment123</password>
</server>
</servers>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
Just use one entry in setttings.xml like that
<server>
<id>nexus</id>
<username>deployment</username>
<password>deployment123</password>
</server>
and then in distributionManagement in your pom.xml's you use something like that
<distributionManagement>
<repository>
<id>nexus</id>
<name>Nexus Releases</name>
<url>http://localhost:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<name>Nexus Snapshot</name>
<url>http://localhost:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
For fully working setup with this look at the Nexus Book Examples project that are used in the trial guide. You can add a site with the same id as well, of course. Keep in mind that there is no problem if the id;s are the same as they just detail the identifier of the server element in settings to look for and are NOT an id element for the repository. Imho it should be called serverId or something to be clearer, but thats a different story.
Not a solution but a workaround:
settings.xml will handle system properties and environment variables. So if you're not fussed about putting your server authentication details in a script or in your environment, you can stick with three server credentials but eliminate the need to update all three of them in favour of updating your script or environments (I've put examples for both options in this snippet):
<servers>
<server>
<id>releases</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
<server>
<id>snapshots</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
<server>
<id>site</id>
<username>${env.NEXUS_USERNAME}</username> <!-- Env var -->
<password>${nexus.password}</password> <!-- System (-D) var -->
</server>
</servers>
Unfortunately there's no <properties> element supported in settings.xml!
Aside: maven already handles the snapshots and releases repositories within nexus, and that is the better way to do things. Your posted settings.xml even enables them already. Why do you need separate repository entries for snapshots and releases?
It looks like you mistaken things here. The given credentials and id's are for the distributionManagement and not for the access to the Nexus in this case. Apart from that you need three different username, password combinations cause you have three possible things releases, snapshots and site. So not a big deal.
Aprt from that i would suggest to upgrade Maven into Maven 3.X line cause Maven 2.2.1 is a little bit out of date.

What does "http://central" mean in my Maven settings.xml?

I've been copying "sample" settings.xml files for ages now, and almost all of them seem to include a repository with the URL http://central. This bugs me, because of course there could actually be a machine on the local domain called "central", so this is a valid URN, but it also must (might?) have some special meaning to Maven.
Is it just shorthand that's commonly used, but the actual URL is ignored? Could I replace it with something else, or remove it entirely? Is it documented anywhere?
If it matters, I develop on a corporate network that has an internal iBiblio mirror, that acts as "central" for us.
AFAIK, it is a bogus URL which mentions at Configure Maven to Download from Nexus as the following example: -
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
The nexus profile is configured to download from the central repository with a bogus URL of http://central.
This URL is overridden by the mirror setting in the same settings.xml file to point to the URL of your single Nexus group. The nexus group is then listed as an active profile in the activeProfiles element.
I hope this may help.
We also used exactly this sample config, even with the same comments for about 15(!) years without any problems. For maven builds it does not matter, as always nexus is requested for any dependencies.
But today I tried to built a project with a combined ant+maven build which failed to get dependencies via artifact:remoteRepository Task from central Repo.
The solution was to fix the "url" tag in the central repo: https://repo.maven.apache.org/maven2
So it looks like it doesn't matter in most cases, but to avoid any corner cases, always use the right url.

The authorization of the Artifactory in Jenkins does not work

I´m using Artifactory 2.4.0 and Jenkins 1.438 and I have maven project with several modules. Need to deploy all modules(jars and one resulting war)
into remote Artifactory server by Jenkins.
My user admin for artifactory was with default password (password) and all builds that I tried to execute on jenkins works fine. So when I resolved
to change de Artifactory admin password and update my settings with the new credentials of admin, I had the following error on jenkins build log:
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project pilotoExemplo: Failed to deploy artifacts:
Could not transfer artifact br.com.pilotoExemplo:pilotoExemplo:pom:2.1.0.11-20120705.160113-1 from/to snapshot
({ip_server}/artifactory/libs-snapshot-local): Failed to transfer file:
{ip_server}/artifactory/libs-snapshot-local/br/com/pilotoExemplo/pilotoExemplo/2.1.0.11-SNAPSHOT/pilotoExemplo-2.1.0.11-20120705.160113-1.pom.
Return code is: 401
Anyone already saw this problem before? I don´t found anything like this search on the google.
Here is my settings.xml:
<mirrors>
<mirror>
<mirrorOf>*</mirrorOf>
<name>repositorio</name>
<url>{ip_server}/artifactory/repo</url>
<id>repositorio</id>
</mirror>
</mirrors>
<profiles>
<profile>
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>{ip_server}/artifactory/libs-release/</url>
</repository>
<repository>
<snapshots />
<id>snapshots</id>
<name>libs-snapshot</name>
<url>{ip_server}/artifactory/libs-snapshot/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>plugins-release</name>
<url>{ip_server}/artifactory/plugins-release</url>
</pluginRepository>
</pluginRepositories>
<id>artifactory</id>
<distributionManagement>
<repository>
<id>release</id>
<url>{ip_server}/artifactory/libs-release-local/</url>
</repository>
<snapshotRepository>
<id>snapshot</id>
<url>{ip_server}/artifactory/libs-snapshot-local/</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
<servers>
<server>
<id>snapshot</id>
<username>admin</username>
<password>newPassword</password>
</server>
<server>
<id>release</id>
<username>admin</username>
<password>newPassword</password>
</server>
<server>
<id>repositorio</id>
<username>admin</username>
<password>newPassword</password>
</server>
</servers>
As far as I know Jenkins jobs can have their own M2 repository, or they use the repository of the user. So the answer could be, that your jenkins is running as a service (maybe as local system account), and not in the name of your user.
You can check the user name at the Jenkins setting/system information page (yourcontextroot/systemInfo). So basicly the solution is to put the same settings file for the running user, like you have.
Tip to solve the problem with the clear text password:
Access and login into Artifactory.
Once you are logged in, click over your user name, on the superior right corner of the screen.
Put your password then clique in the em Unlockbutton, enabling the encrypted password.
Copy the tag that will be showed on the inferior part of the screen and paste it into the settings.xml file. If you prefer to just copy the password, be sure about let it exactly equals the tag showed below, including the "\" at the beginning of the password.
Remember to adjust the tag with the id of your server, defined into the tag, in your POM.xml
Click in Update button and ready! Check if everything will occur well at the next project's publication.

Resources