Skip to content

Qbandev/jfrog-token-tool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jfrog-token-tool – password-less JFrog access tokens for any AWS workload

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-tool closes that gap: with nothing but the temporary AWS credentials you already have the tool signs a GetCallerIdentity request, 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.


1 . How it works

  1. 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).
  2. It signs a virtual GET https://sts.amazonaws.com?Action=GetCallerIdentity request with SigV4-A (Elliptic-Curve variant).
  3. It exchanges those signed headers with Artifactory and prints the bearer token to stdout.

2 . Prerequisites

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

2.1 IAM role permissions

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.

2.2 JFrog user & AWS role mapping

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.


3 . Quick-start

3.1 Building and testing with Makefile

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

3.1 Building and testing manually

# 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 stdout

The 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/ping

That's it—you've obtained a short-lived JFrog token without storing any long-lived secrets.


4 . Security notes

  • The program never transmits your AWS keys anywhere – signing is done locally.
  • You can choose the token TTL via the TOKEN_TTL field.

5 . License

This utility is extracted from the jfrog-registry-operator project and retains the same Apache-2.0 license.

About

JFrog password-less token helper for AWS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published