Create an Assumable Identity for a CLI session authenticated with Keycloak
Procedural tutorial outlining how to create a Chainguard identity that can be assumed by a Keycloak user.
This tutorial details how to set up remote Alpine package (apk) repositories with JFrog Artifactory, which can provide pull-through caches for Chainguard package repositories. Specifically, this guide walks you through how to set up remote Artifactory repositories to serve as pull-through caches for a Chainguard Private APK Repository as well as Chainguard’s public package repositories. The guide also outlines how to configure a container image build to pull APK packages from these remote repositories using tokens generated by Artifactory.
In order to complete this tutorial, you need the following:
chainctl
role_bindings.create
); this capability is available to users with the owner
role.When configuring an Artifactory remote repository to function as a pull-through cache for packages from a Chainguard private APK repository, the remote repository must authenticate to Chainguard. This section outlines the steps necessary to create a Chainguard pull token and configure the required permissions to access your Chainguard organization’s private APK repository:
Set your Chainguard organization identifier as an environment variable. Replace the example.org
placeholder with your organization’s name as it appears in the Chainguard Console:
export CHAINGUARD_ORG=example.org
Next, generate a pull token:
chainctl auth pull-token --parent=${CHAINGUARD_ORG} -o env
The command outputs the credentials as export
commands you can run to set them as environment variables:
export CHAINGUARD_IDENTITY_ID=<id>
export CHAINGUARD_TOKEN=<token>
Run the first of these commands to create an environment variable for the identity:
export CHAINGUARD_IDENTITY_ID=<id>
Be sure to note both the identity and token values to use when you create a remote Artifactory repository in the next section.
With the environment variables in place, create a role binding to bind the pull token identity the apk.pull
role:
chainctl iam role-bindings create \
--parent=${CHAINGUARD_ORG} \
--identity=${CHAINGUARD_IDENTITY_ID} \
--role=apk.pull
This enables the identity to download packages from the private APK repository of the organization.
Now that you have an identity with permissions to do so, you can set up a remote Artifactory repository to reach your private APK repository.
To set up the remote repository:
This takes you to a Basic configuration tab where you can enter the following details for the remote repository:
cg-private
.https://apk.cgr.dev/${CHAINGUARD_ORG}
, but with your organization’s actual name in place of ${CHAINGUARD_ORG}
. For example, if your organization is named example
use https://apk.cgr.dev/example
.CHAINGUARD_IDENTITY_ID
variable.CHAINGUARD_TOKEN
.Then, navigate to the Advanced configuration tab and enter the following details:
Click the Create Remote Repository button to create the remote repository and return to the Repositories page.
Note: For more information on how to set up a remote repository in Artifactory, refer to the official documentation.
Before testing whether you’re able to pull packages through the remote Artifactory repository, you must retrieve a token generated for it by Artifactory.
With this token in hand, run the following export
command to create an environment variable, replacing my-token
with the token you noted down. You will use this environment variable in the following section as you test out the remote repository:
export CG_PRIVATE_TOKEN=my-token
Additionally, create two more environment variables to hold your Artifactory username and server name:
export ARTIFACTORY_USERNAME=my-user-profile
export ARTIFACTORY_SERVER_NAME=my-artifactory-hostname
If you aren’t sure of these values, you can find them in the command from the Set Up An Alpine Client window where you retrieved the token:
sudo sh -c "echo 'https://linky:<TOKEN>@example-server-name.jfrog.io/artifactory/cg-private/<BRANCH>/<REPOSITORY>'" >> /etc/apk/repositories
In this example, the Artifactory username is linky
and the hostname is example-hostname
.
Note: If your Artifactory username is an email address, you must percent-encode the
@
sign, as inexport ARTIFACTORY_USERNAME=linky%40example.com
. Here, the Artifactory username islinky@example.com
, but it must be entered into the environment variable aslinky%40example.com
.
This section outlines how to build a container image using a Chainguard image as a base and configure it to pull packages from the private APK repositories through your remote Artifactory repository.
Open a terminal and create a Dockerfile:
cat > Dockerfile <<EOF
FROM cgr.dev/chainguard/python:latest-dev
USER root
RUN cp /etc/apk/repositories /etc/apk/repositories.disabled
RUN echo 'https://$ARTIFACTORY_USERNAME:$CG_PRIVATE_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-private/' > /etc/apk/repositories
RUN apk add sed
USER nonroot
EOF
This Dockerfile uses the python:latest-dev
image. You don’t have to use this particular image, but because we are using the apk
command to install a package from cgr-private
in this Dockerfile, you should use a Chainguard container image that has this package manager available.
Note that this Dockerfile renames the default /etc/apk/repositories
file. This isn’t necessary, but doing so allows you to ensure that you’re actually downloading packages from the remote Artifactory repositories instead of the default ones.
Additionally, be aware that there are limitations to what packages are available from your organization’s private APK repository. For instance, your organization may not have access to the sed
package. Refer to our private APK repository documentation for more information.
After creating the Dockerfile, build the image. Here, we tag the image ar-build
:
docker build -t ar-build .
This command’s output will show that the sed
package was installed as expected:
. . .
=> [4/4] RUN apk add sed 2.8s
. . .
You can confirm that this package was pulled through Artifactory with the Artifact Repository Browser in the Artifactory dashboard:
cg-private
Artifactory repository.There, you will find the sed
package listed, along with any other packages you’ve pulled through the remote repository.
You also have access to the public chainguard
and extra-packages
repositories. Because these repositories are public, they do not require authentication. To set up a pull-through cache for these package repositories on Artifactory, you can follow the same procedure outlined previously for the private APK repository.
You must create two remote repositories within Artifactory — one for each public package repo — by following the same steps as before:
Enter the following details for the two remote repositories:
cg-chainguard
and cg-extras
.https://virtualapk.cgr.dev/<ORGANIZATION-ID>/chainguard
for the chainguard
repository and https://virtualapk.cgr.dev/<ORGANIZATION-ID>/extra-packages
for the extra-packages
repository.
<ORGANIZATION-ID>
placeholder with your Chainguard organization’s UID. You can find this by running the chainctl iam organizations list -o table
; the UID is the value in your organization’s ID
column. Alternatively, you can find it by checking the Settings ⇒ General page in the Chainguard Console.You do not need to set any values for the User Name or Password / Access Token fields, as the public repositories do not require authentication.
Next, for both repositories, navigate to the Advanced configuration tab and check the Disable URL Normalization option. This will prevent URL normalization from invalidating the URLs that packages are served from.
Keep all the remaining fields set to their default values and click the Create Remote Repository button. This creates the remote repository and returns you to the Repositories page.
After creating both repositories, generate and retrieve a token for each one as you did for the cg-private
remote repository:
Next, copy the resulting tokens to create a pair of environment variables. For the cg-chainguard
repository’s token:
export CG_TOKEN=<cg-chainguard-token>
Then for the cg-extras
repo’s token:
export EXTRAS_TOKEN=<cg-extras-token>
Following that, you can use these environment variables, along with a few created earlier in the guide, to create a Dockerfile as you previously did for the cg-private
repository:
cat > Dockerfile.repos <<EOF
FROM cgr.dev/chainguard/python:latest-dev
USER root
RUN cp /etc/apk/repositories /etc/apk/repositories.disabled
RUN echo 'https://$ARTIFACTORY_USERNAME:$CG_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-chainguard/' > /etc/apk/repositories
RUN echo 'https://$ARTIFACTORY_USERNAME:$EXTRAS_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-extras/' >> /etc/apk/repositories
RUN apk add c-ares
EOF
Following that, build the image:
docker build -t ar-repos -f Dockerfile.repos .
As this command runs, it installs the c-ares
package into the image.
If you run into issues when trying to pull from Chainguard’s package repositories through Artifactory, you can try checking for these common pitfalls:
@
sign can lead to errors. Be sure that you’re using a user profile with a name that only contains letters and numbers. If you must use a profile with an email address for a name, try percent-encoding the @
sign by replacing it with %40
.package mentioned in index not found
, it usually means Artifactory or a CDN is normalizing or rewriting APK URLs (often by stripping query strings, collapsing path segments, or altering tokens). To prevnt this, ensure that Artifactory’s Disable URL Normalization option is checked in order to preserve exact filenames and tokens.If you haven’t already done so, you may find it useful to review our Registry Overview to learn more about Chainguard’s registry. You can also learn more about Chainguard Containers by referring to our documentation, and learn more about working with the Chainguard platform by reviewing our Administration documentation. If you’d like to learn more about JFrog Artifactory, we encourage you to refer to the official Artifactory documentation.
Last updated: 2025-09-24 06:00