-
Hello, I'm having a trouble with publishing packages to Jfrog's PyPi Artifactory by using a access token. Unfortunately only the packages_publish:
needs:
- generate_packages
- packages_test
runs-on: ubuntu-20.04
container: <PYTHONRUNTIME_IMAGE>
env:
OIDC_AUDIENCE: 'jfrog-github'
OIDC_ITEGRATION_NAME: 'github-oidc-integration'
#if: github.ref == 'refs/heads/main'
permissions: write-all
steps:
- name: Install dependencies for auth
run: apt update && apt install -y jq
- name: Get ID Token
id: idtoken
run: |
ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=$OIDC_AUDIENCE" | jq .value | tr -d '"')
echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_OUTPUT
- name: Fetch Access Token from Artifactory
id: fetch_access_token
env:
ID_TOKEN: ${{ steps.idtoken.outputs.id_token }}
run: |
ACCESS_TOKEN=$(curl \
-X POST \
-H "Content-type: application/json" \
https://example.jfrog.io/access/api/v1/oidc/token \
-d \
"{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"$ID_TOKEN\", \"provider_name\": \"$OIDC_ITEGRATION_NAME\"}" | jq .access_token | tr -d '"')
echo ACCESS_TOKEN=$ACCESS_TOKEN >> $GITHUB_OUTPUT
- uses: actions/checkout@v3
- name: Publish to artifactory
env:
POETRY_PYPI_TOKEN_EXAMPLE: ${{ steps.fetch_access_token.outputs.access_token }}
POETRY_REPOSITORIES_EXAMPLE_URL: 'https://example.jfrog.io/artifactory/api/pypi/pypi-general-local'
run: |
cd packages/<package-example>
sed -i "0,/\(version = \"[0-9]\+.[0-9]\+\)\"/s//\1.${{ github.run_number }}\"/" pyproject.toml
poetry config pypi-token.example $POETRY_PYPI_TOKEN_EXAMPLE
poetry publish --build -r example -vvv Full error Publish output:
This works: - name: Publish to artifactory
env:
POETRY_HTTP_BASIC_EXAMPLE_USERNAME: '${{ vars.jfrog_username }}`
POETRY_HTTP_BASIC_EXAMPLE_PASSWORD: '${{ steps.fetch_access_token.outputs.access_token }}'
POETRY_REPOSITORIES_EXAMPLE_URL: 'https://example.jfrog.io/artifactory/api/pypi/pypi-general-local'
run: |
cd packages/<package-example>
sed -i "0,/\(version = \"[0-9]\+.[0-9]\+\)\"/s//\1.${{ github.run_number }}\"/" pyproject.toml
poetry config http-basic.example $POETRY_HTTP_BASIC_EXAMPLE_USERNAME $POETRY_HTTP_BASIC_EXAMPLE_PASSWORD
poetry publish --build -r example
I've also tried the |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
JFrog access tokens do not work the same way as PyPI tokens. https://jfrog.com/help/r/jfrog-platform-administration-documentation/basic-authentication You either need to use basic authentication with the username set to the user generating the token (see above link), or make use of an auth header. The latter is not a feature that is supported, but potentially something we can add as a new feature if there is enough appetite for this. With the above in mind, I think this is working as designed at the moment. |
Beta Was this translation helpful? Give feedback.
-
I figured out how to make it work using basic authentication and Jfrog's OpenID Connect Integration. With this method, you don't need to store poetry Token (JWT) will be used as the password and the username that is associated with the token will be parsed from the token. To make this work, you need to:
Example: packages_publish:
runs-on: ubuntu-latest
container: ghcr.io/<poetry_image>
env:
OIDC_AUDIENCE: 'jfrog-github' # must match the exact name set in Jfrog's OIDC Integration
OIDC_ITEGRATION_NAME: 'github-oidc-integration' # must match the exact name set in Jfrog's OIDC Integration
permissions:
id-token: write # this permission is mandatory for Jfrogs's OpenID Connect Integration/trusted publishing
contents: read # required if job’s steps are manipulating with the repository, e.g. actions/checkout@v4.
packages: read # required if job is using a container image
steps:
- name: Install dependencies for auth
run: apt update && apt install -y jq
- name: Get ID Token
run: |
ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=$OIDC_AUDIENCE" | jq .value | tr -d '"')
echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_ENV
- name: Fetch Access Token from Artifactory
env:
ID_TOKEN: ${{ env.ID_TOKEN }}
run: |
ACCESS_TOKEN=$(curl \
-X POST \
-H "Content-type: application/json" \
https://example.jfrog.io/access/api/v1/oidc/token \
-d \
"{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"$ID_TOKEN\", \"provider_name\": \"$OIDC_ITEGRATION_NAME\"}" | jq .access_token | tr -d '"')
echo "::add-mask::$ACCESS_TOKEN"
echo "ACCESS_TOKEN=${ACCESS_TOKEN}" >> $GITHUB_ENV
- name: Parse username from access-token
env:
ACCESS_TOKEN: ${{ env.ACCESS_TOKEN }}
shell: bash
run: |
USERNAME=$(jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$ACCESS_TOKEN" | jq -r .sub | sed 's/.*users\///')
echo USERNAME=${USERNAME} >> $GITHUB_ENV
- uses: actions/checkout@v4
- name: Publish to artifactory
env:
JFROG_SERVICE_USERNAME: ${{ env.USERNAME }}
JFROG_SERVICE_ACCESS_TOKEN: ${{ env.ACCESS_TOKEN }}
run: |
poetry config repositories.example"https://example.jfrog.io/artifactory/api/pypi/example"
poetry config http-basic.example$JFROG_SERVICE_USERNAME $JFROG_SERVICE_ACCESS_TOKEN
poetry publish --build -r example |
Beta Was this translation helpful? Give feedback.
I figured out how to make it work using basic authentication and Jfrog's OpenID Connect Integration.
With this method, you don't need to store poetry
username
andpassword
credentials in GitHub secrets.Token (JWT) will be used as the password and the username that is associated with the token will be parsed from the token.
To make this work, you need to: