There are situations in which you want to use your own Artifactory server for resolving Maven dependencies. Maybe you have private artifacts or are not yet in the process of migrating from Artifactory to GitHub Packages.
What is the goal of this blog post?
This blog shows you how you can grant your GitHub Actions CI/CD pipeline access to your private Maven repository hosted with Artifactory. My requirements have been the following:
- In our GitHub Actions build process, download dependent libraries from our internal Artifactory server.
- Only allow access to a single Maven repository in our Artifactory instance but not all of them.
- Don’t create any additional CI/CD users in Artifactory or downstream user directories.
After reading through Artifactory’s documentation, I realized that I could use a transient user in Artifactory. This concept is explicitly designed for CI/CD processes.
Restrict access by creating a group in Artifactory
For security reasons, I only wanted to give access to one of our Maven repository in our Artifactory instance but not all. Transient users are not visible in Artifactory. So I had to create a specific group which can be used for permission mapping.
Create the new group at Admin > Security > Groups > New. You can use any name you want, but you need to note it. The group name (${ARTIFACTORY_GROUP_NAME}) is required in the next step.
After that I had to assign the proper permission to the newly created group. Navigate to Admin > Security > Permissions > New and select the proper repository on the Resources tab. On the Group tab, you have to select the recently created group and check the Read checkbox in the Repository Actions panel.
Generate an access token in Artifactory
As already mentioned, the access token is used by GitHub Actions to gain access to the Artifactory server.
The Artifactory documentation does not explicitly mention it but you have to generate the access token with help of an API request. There is (seemingly?) no way to generate a normal access token through the web user interface. As written in the Artifactory REST API documentation, you need to call the Create Token endpoint.
On the command line, request a new token by calling
curl -u "${USERNAME}:${PASSWORD}" -XPOST "https://${ARTIFACTORY_HOST}/artifactory/api/security/token" \
-d "username=github-actions" \
-d scope="member-of-groups:${ARTIFACTORY_GROUP_NAME}" \
-d expires_in=0
Replace the ${…} variables with the appropriate values.
- The username variable only exists for convenience reasons. There is no need that the user itself exists. It is just important that member-of-groups points to our previosuly created group.
- With expires_in you can set the expiration of the access token in seconds. A zero means no expiration is set.
Artifactory will respond with a body like this:
200
{
"access_token": "xajajaajajajaja...",
"expires_in": 0,
"scope": "api:* member-of-groups:ci-cd",
"token_type": "Bearer"
}
Note the content of the access_token field (${ARTIFACTORY_ACCESS_TOKEN}). This is needed in your GitHub Action and pom.xml.
Configure your Maven project
Your Maven configuration has to be changed so GitHub Actions uses your Artifactory server.
Update your pom.xml
To make external dependencies more obvious, I decided to put the private repository in our pom.xml. You can alternatively skip it and use the settings.xml. But I’d recommend it this way: new developers will see during the checkout that this repository must be configured just by looking at the POM.
Just add the URL of your Artifactory’s repository URL to the pom.xml:
...
</dependencies>
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>artifactory</id>
<name>my-repo</name>
<url>https://${ARTIFACTORY_HOST}/artifactory/my-repo</url>
</repository>
</repositories>
...
Note the name of the artifactory server id (<id>${MAVEN_SERVER_ID}</id>).
Test the access token by putting it in your local settings.xml
In your settings.xml (e.g. ~/.m2/settings.xml), you have to add a new server:
<servers>
<server>
<id>${MAVEN_SERVER_ID}</id>
<username>github-actions</username>
<password>xajajaajajajaja...</password>
</server>
</servers>
- Replace ${MAVEN_SERVER_ID} with the id you have previously used in your pom.xml
- Update the content of the password element with the ${ARTIFACTORY_ACCESS_TOKEN} value.
When you run mvn package, your Artifactory server should be used to download the private dependencies.
Configure GitHub Actions
Add secrets for the workflow
In your GitHub project, navigate to Settings > Secrets and add two new secrets:
- ARTIFACTORY_TOKEN with the content of your ${ARTIFACTORY_ACCESS_TOKEN}
- ARTIFACTORY_USERNAME with any content (see transient user above); for convenience reasons I suggest you are using the same username you have already used in the curl command.
After adding both environment variables, your Secrets page should look like the following:
Configure the GitHub Actions workflow
The action/setup-java action already contains the required workflow modifications. The action allows us to add a custom repository to the settings.xml. Customize your GitHub Actions workflow like this:
name: Build Dreitier
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Set up our custom Artifactory instance
uses: actions/setup-java@v1
with: # running setup-java again overwrites the settings.xml
java-version: 1.8
server-id: artifactory # value of repository/id field of the pom.xml
server-username: ARTIFACTORY_USERNAME_REF # env variable name for username of Artifactory server; value can be anything as it is a transient user
server-password: ARTIFACTORY_TOKEN_REF # env variable name for Artifactory access token
# after running this action, the <username> tag contains ${env.ARTIFACTORY_USERNAME_REF} and <password> contains ${env.ARTIFACTORY_TOKEN_REF}
- name: Build with Maven
run: mvn -B package
env:
# assign the environment variable env.ARTIFACTORY_TOKEN_REF with the previously configured ARTIFACTORY_TOKEN
ARTIFACTORY_TOKEN_REF: ${{ secrets.ARTIFACTORY_TOKEN }}
# assign the environment variable env.ARTIFACTORY_USERNAME_REF with the previously configured ARTIFACTORY_USERNAME
ARTIFACTORY_USERNAME_REF: ${{ secrets.ARTIFACTORY_USERNAME }}
When running the build process, you will see that our custom Artifactory instance is used:
1 Comment
Using GitHub Workflow with Maven dependencices from a private GitHub Package Registry - schakko.de · February 11, 2022 at 6:10 am
[…] for storing the repository and doing CI/CD stuff. We included some Maven dependencies from our company’s Artifactory in GitHub Actions CI […]
Comments are closed.