Skip to content

Commit 65e62a8

Browse files
committed
ci: add JFrog Artifactory proxy for npm registry access
Hardened runners block direct access to public registries. Configure JFrog Artifactory as an npm proxy using OIDC token exchange per the remote registry access guidance. Added to all jobs that run `npm ci`: lint, unit-test, e2e-test (main.yml) and build (release.yml). The coverage job and dco-check workflow do not access npm and are left unchanged. Adds `id-token: write` permission for the OIDC token exchange. Co-authored-by: Isaac
1 parent 3e17e84 commit 65e62a8

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

.github/workflows/main.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010

1111
permissions:
1212
contents: read
13+
id-token: write
1314

1415
jobs:
1516
lint:
@@ -18,6 +19,33 @@ jobs:
1819
labels: linux-ubuntu-latest
1920
steps:
2021
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
22+
- name: Get JFrog OIDC token
23+
run: |
24+
set -euo pipefail
25+
ID_TOKEN=$(curl -sLS \
26+
-H "User-Agent: actions/oidc-client" \
27+
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
28+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
29+
echo "::add-mask::${ID_TOKEN}"
30+
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
31+
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
32+
-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\": \"github-actions\"}" | jq .access_token | tr -d '"')
33+
echo "::add-mask::${ACCESS_TOKEN}"
34+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
35+
echo "FAIL: Could not extract JFrog access token"
36+
exit 1
37+
fi
38+
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
39+
echo "JFrog OIDC token obtained successfully"
40+
- name: Configure npm for JFrog
41+
run: |
42+
set -euo pipefail
43+
cat > ~/.npmrc << EOF
44+
registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
45+
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
46+
always-auth=true
47+
EOF
48+
echo "npm configured to use JFrog registry"
2149
- name: Cache node modules
2250
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
2351
env:
@@ -57,6 +85,33 @@ jobs:
5785
uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4
5886
with:
5987
python-version: '3.10'
88+
- name: Get JFrog OIDC token
89+
run: |
90+
set -euo pipefail
91+
ID_TOKEN=$(curl -sLS \
92+
-H "User-Agent: actions/oidc-client" \
93+
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
94+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
95+
echo "::add-mask::${ID_TOKEN}"
96+
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
97+
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
98+
-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\": \"github-actions\"}" | jq .access_token | tr -d '"')
99+
echo "::add-mask::${ACCESS_TOKEN}"
100+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
101+
echo "FAIL: Could not extract JFrog access token"
102+
exit 1
103+
fi
104+
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
105+
echo "JFrog OIDC token obtained successfully"
106+
- name: Configure npm for JFrog
107+
run: |
108+
set -euo pipefail
109+
cat > ~/.npmrc << EOF
110+
registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
111+
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
112+
always-auth=true
113+
EOF
114+
echo "npm configured to use JFrog registry"
60115
- name: Cache node modules
61116
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
62117
with:
@@ -96,6 +151,33 @@ jobs:
96151

97152
steps:
98153
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
154+
- name: Get JFrog OIDC token
155+
run: |
156+
set -euo pipefail
157+
ID_TOKEN=$(curl -sLS \
158+
-H "User-Agent: actions/oidc-client" \
159+
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
160+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
161+
echo "::add-mask::${ID_TOKEN}"
162+
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
163+
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
164+
-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\": \"github-actions\"}" | jq .access_token | tr -d '"')
165+
echo "::add-mask::${ACCESS_TOKEN}"
166+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
167+
echo "FAIL: Could not extract JFrog access token"
168+
exit 1
169+
fi
170+
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
171+
echo "JFrog OIDC token obtained successfully"
172+
- name: Configure npm for JFrog
173+
run: |
174+
set -euo pipefail
175+
cat > ~/.npmrc << EOF
176+
registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
177+
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
178+
always-auth=true
179+
EOF
180+
echo "npm configured to use JFrog registry"
99181
- name: Cache node modules
100182
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
101183
with:

.github/workflows/release.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,39 @@ jobs:
1111
labels: linux-ubuntu-latest
1212
permissions:
1313
contents: read
14+
id-token: write
1415
steps:
1516
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
1617
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
1718
with:
1819
node-version: 22
20+
- name: Get JFrog OIDC token
21+
run: |
22+
set -euo pipefail
23+
ID_TOKEN=$(curl -sLS \
24+
-H "User-Agent: actions/oidc-client" \
25+
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
26+
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
27+
echo "::add-mask::${ID_TOKEN}"
28+
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
29+
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
30+
-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\": \"github-actions\"}" | jq .access_token | tr -d '"')
31+
echo "::add-mask::${ACCESS_TOKEN}"
32+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
33+
echo "FAIL: Could not extract JFrog access token"
34+
exit 1
35+
fi
36+
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
37+
echo "JFrog OIDC token obtained successfully"
38+
- name: Configure npm for JFrog
39+
run: |
40+
set -euo pipefail
41+
cat > ~/.npmrc << EOF
42+
registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
43+
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
44+
always-auth=true
45+
EOF
46+
echo "npm configured to use JFrog registry"
1947
- run: npm ci
2048
- run: npm pack
2149
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4

0 commit comments

Comments
 (0)