jfrog-token-tool is a tiny Go utility that returns a short-lived Artifactory access token using AWS SigV4-A authentication.
All you need are temporary AWS credentials—no passwords or long-lived API keys are stored.
Why does this project exist?
JFrog officially ships an AssumeRole integration for its Helm-based EKS installation, however the same capability is missing for all other AWS runtimes.
If your workloads run on ECS/Fargate, Lambda, EC2, or you simply need a developer CLI / CI pipeline to talk to your Artifactory, you are currently left without an ergonomic way to mint tokens.
jfrog-token-toolcloses that gap: with nothing but the temporary AWS credentials you already have the tool signs aGetCallerIdentityrequest, exchanges it against the /access/api/v1/aws/token endpoint and prints a ready-to-use bearer token.
The resulting token can be injected into your Docker build, Terraform run, Maven/Gradle build, etc. without ever persisting a secret.
- The program automatically picks up AWS credentials from any available source: exported environment variables, the ECS/Fargate task-role endpoint, or the EC2 Instance Metadata Service (instance-profile role).
- It signs a virtual
GET https://sts.amazonaws.com?Action=GetCallerIdentityrequest with SigV4-A (Elliptic-Curve variant). - It exchanges those signed headers with Artifactory and prints the bearer token to stdout.
| requirement | why |
|---|---|
| Go 1.20+ | build the helper (no CGO, builds in seconds) |
| Temporary AWS credentials | any of: aws sts assume-role, EC2 instance profile, AWS SSO, etc. |
Optional aws CLI |
convenient way to obtain the temp credentials |
| AWS IAM role mapped in JFrog | EC2/ECS/Lambda/CI role whose temporary credentials will be used to sign the request |
| Artifactory unmanaged user | local user in JFrog linked to the IAM role; the issued token will belong to this user |
For CI/CD you can create a role in AWS, because the SigV4-A headers you generate prove possession of that specific role's temporary credentials. Artifactory will only issue a token when the IAM role in the signature matches a role that it knows (via the role-to-user mapping). All example commands and Terraform snippets below therefore reference the same ARN:
arn:aws:iam::000000000000:role/atlantis
The role you will assume must be allowed to prove its identity to STS and, optionally, obtain federation tokens. Attach the following inline policy to the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:GetCallerIdentity",
"Resource": "arn:aws:iam::000000000000:role/atlantis"
}
]
}And make sure the role can be assumed by the principal that will run the helper (SSO user, CI role, etc.). Example trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/ci-bot"
},
"Action": "sts:AssumeRole"
}
]
}Replace the principal ARN with your own IAM user or role that initiates the token-generation script.
The helper does not need the AWS SDK at runtime – only during compilation. The resulting binary is a few MB in size and has no dependencies.
You must give Artifactory a local (unmanaged) user that will own the token it issues and map that user to the AWS IAM role you assume.
If you manage JFrog with Terraform the configuration looks like:
# Atlantis service-account user (no UI/password log-in)
resource "artifactory_unmanaged_user" "atlantis_service_account" {
name = "atlantis"
email = "atlantis@atlantis.io"
groups = ["readonly"] # readonly or any group you need
disable_ui_access = true # cannot log in via UI
internal_password_disabled = true # cannot set a password
}
# Map the AWS IAM role to that user so /aws/token can exchange it
resource "platform_aws_iam_role" "atlantis_aws_role" {
username = artifactory_unmanaged_user.atlantis_service_account.name
iam_role = "arn:aws:iam::000000000000:role/atlantis" # <-- role used in the script
}You can also create the user and the iam role link using the Jfrog api: https://jfrog.com/help/r/jfrog-rest-apis/create-user https://jfrog.com/help/r/jfrog-rest-apis/get-aws-iam-role
Example (admin API key assumed):
# create unmanaged user
curl -X POST "https://${JFROG_URL}/access/api/v1/users" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${admin_token}" \
-d '{
"name" : "atlantis",
"email" : "atlantis@atlantis.io",
"groups": ["readonly"],
"admin" : false,
"profile_updatable": false,
"disable_ui_access": true,
"internal_password_disabled": true
}'
# link AWS role to that user
curl -X PUT "https://${JFROG_URL}/access/api/v1/aws/iam/roles/arn:aws:iam::000000000000:role/atlantis" \
-H "Authorization: Bearer ${admin_token}" \
-d '{"username": "atlantis"}'These API calls achieve the same outcome as the Terraform resources if you manage JFrog manually or via another automation tool.
After applying those resources, calls to /access/api/v1/aws/token that present a SigV4-A signature produced from the specified IAM role will result in a token issued for the atlantis JFrog user.
For convenience the repository includes a Makefile.
make # builds the binary (same as make build)
make run # build + execute (prints the access token—requires TOKEN_TTL and JFROG_URL environment variables and valid AWS credentials)
make test # run all unit tests (crypto helpers etc.)
make clean # delete compiled binary# 1. clone / copy the repo
cd jfrog-token-tool
# 2. build
go build -o sigv4a-headers ./cmd/sigv4a
# 3. fetch temporary AWS creds for the Atlantis role (you need to have permissions assume that role in the **trust relationship**)
export ROLE_ARN="arn:aws:iam::000000000000:role/atlantis"
read AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN <<<"$(\
aws sts assume-role --role-arn "$ROLE_ARN" \
--role-session-name sigv4a-test \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text)"
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
# 4. Add the environment variables
export TOKEN_TTL=3600 # Token TTL
export JFROG_URL="company.jfrog.io" # Company Jfrog url
# 5. retrieve the Artifactory access token
./sigv4a-headers # prints the token to stdoutThe program signs a GetCallerIdentity request, exchanges it with JFrog, and prints the resulting token. Capture it in a variable:
access_token=$(./sigv4a-headers)
# use the token
curl -H "Authorization: Bearer ${access_token}" \
https://"${JFROG_URL}"/artifactory/api/system/pingThat's it—you've obtained a short-lived JFrog token without storing any long-lived secrets.
- The program never transmits your AWS keys anywhere – signing is done locally.
- You can choose the token TTL via the
TOKEN_TTLfield.
This utility is extracted from the jfrog-registry-operator project and retains the same Apache-2.0 license.