Skip to content

Commit 3cd3eb0

Browse files
authored
Replace NGINX_PAT with Github Apps (#10477)
* Replace NGINX_PAT with Github Apps * Refactor GitHub App token generation and secret handling in release workflow * Enhance GitHub App private key handling by masking base64 values and individual lines in workflows
1 parent f155064 commit 3cd3eb0

9 files changed

Lines changed: 377 additions & 83 deletions

.github/workflows/cherry-pick.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
uses: nginx/ci-self-hosted/.github/actions/get-from-vault@5c3e1f8b51f66a851fdba80f70e19cf966199730 # main @ 2026-05-22
8181
with:
8282
vault-name: ${{ secrets.COMMON_KEYVAULT_NAME }}
83-
secret-names: "nginx-bot-cherry-pick-app-client-id, nginx-bot-cherry-pick-app-private-key"
83+
secret-names: "nginx-bot-nic-create-pr-app-client-id, nginx-bot-nic-create-pr-app-private-key"
8484
env-names: "APP_CLIENT_ID, APP_PRIVATE_KEY_B64"
8585

8686
- name: Decode GitHub App private key

.github/workflows/create-release-branch.yml

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,41 @@ jobs:
5151
tenant-id: ${{ secrets.AZURE_COMMON_VAULT_TENANT_ID }}
5252
subscription-id: ${{ secrets.AZURE_COMMON_VAULT_SUBSCRIPTION_ID }}
5353

54-
- name: Setup secrets
55-
id: secrets
54+
- name: Get secrets from vault
55+
uses: nginx/ci-self-hosted/.github/actions/get-from-vault@5c3e1f8b51f66a851fdba80f70e19cf966199730 # main @ 2026-05-22
56+
with:
57+
vault-name: ${{ secrets.COMMON_KEYVAULT_NAME }}
58+
secret-names: "nginx-bot-nic-create-branch-app-client-id, nginx-bot-nic-create-branch-app-private-key"
59+
env-names: "APP_CLIENT_ID, APP_PRIVATE_KEY_B64"
60+
61+
- name: Decode GitHub App private key
62+
id: app_key
5663
run: |
57-
echo "Setting secrets for job"
58-
NGINX_PAT=$(az keyvault secret show --name nginx-bot-pat --vault-name ${{ secrets.COMMON_KEYVAULT_NAME }} --query value -o tsv)
59-
echo "::add-mask::$NGINX_PAT"
60-
echo "NGINX_PAT=$NGINX_PAT" >> $GITHUB_OUTPUT
64+
set +x
65+
# Mask the raw base64 value
66+
echo "::add-mask::$APP_PRIVATE_KEY_B64"
67+
private_key=$(printf '%s' "$APP_PRIVATE_KEY_B64" | base64 -d)
68+
# Mask every line of the decoded PEM key individually
69+
while IFS= read -r line; do
70+
if [[ -n "$line" ]]; then
71+
echo "::add-mask::$line"
72+
fi
73+
done <<< "$private_key"
74+
delimiter="GHEOF_$(openssl rand -hex 12)"
75+
{
76+
echo "private_key<<$delimiter"
77+
echo "$private_key"
78+
echo "$delimiter"
79+
} >> "$GITHUB_OUTPUT"
80+
81+
- name: Generate GitHub App token
82+
id: app_token
83+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
84+
with:
85+
client-id: ${{ env.APP_CLIENT_ID }}
86+
private-key: ${{ steps.app_key.outputs.private_key }}
87+
owner: ${{ github.repository_owner }}
88+
repositories: ${{ github.event.repository.name }}
6189

6290
- name: Create new release branch
6391
run: |
@@ -83,4 +111,4 @@ jobs:
83111
git push --dry-run origin "${branch}"
84112
fi
85113
env:
86-
GITHUB_TOKEN: ${{ steps.secrets.outputs.NGINX_PAT }}
114+
GITHUB_TOKEN: ${{ steps.app_token.outputs.token }}

.github/workflows/external-pr.yml

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,41 @@ jobs:
8484
tenant-id: ${{ secrets.AZURE_COMMON_VAULT_TENANT_ID }}
8585
subscription-id: ${{ secrets.AZURE_COMMON_VAULT_SUBSCRIPTION_ID }}
8686

87-
- name: Setup secrets
88-
id: secrets
87+
- name: Get secrets from vault
88+
uses: nginx/ci-self-hosted/.github/actions/get-from-vault@5c3e1f8b51f66a851fdba80f70e19cf966199730 # main @ 2026-05-22
89+
with:
90+
vault-name: ${{ secrets.COMMON_KEYVAULT_NAME }}
91+
secret-names: "nginx-bot-nic-create-pr-app-client-id, nginx-bot-nic-create-pr-app-private-key"
92+
env-names: "APP_CLIENT_ID, APP_PRIVATE_KEY_B64"
93+
94+
- name: Decode GitHub App private key
95+
id: app_key
8996
run: |
90-
echo "Setting secrets for job"
91-
NGINX_PAT=$(az keyvault secret show --name nginx-bot-pat --vault-name ${{ secrets.COMMON_KEYVAULT_NAME }} --query value -o tsv)
92-
echo "::add-mask::$NGINX_PAT"
93-
echo "NGINX_PAT=$NGINX_PAT" >> $GITHUB_OUTPUT
97+
set +x
98+
# Mask the raw base64 value
99+
echo "::add-mask::$APP_PRIVATE_KEY_B64"
100+
private_key=$(printf '%s' "$APP_PRIVATE_KEY_B64" | base64 -d)
101+
# Mask every line of the decoded PEM key individually
102+
while IFS= read -r line; do
103+
if [[ -n "$line" ]]; then
104+
echo "::add-mask::$line"
105+
fi
106+
done <<< "$private_key"
107+
delimiter="GHEOF_$(openssl rand -hex 12)"
108+
{
109+
echo "private_key<<$delimiter"
110+
echo "$private_key"
111+
echo "$delimiter"
112+
} >> "$GITHUB_OUTPUT"
113+
114+
- name: Generate GitHub App token
115+
id: app_token
116+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
117+
with:
118+
client-id: ${{ env.APP_CLIENT_ID }}
119+
private-key: ${{ steps.app_key.outputs.private_key }}
120+
owner: ${{ github.repository_owner }}
121+
repositories: ${{ github.event.repository.name }}
94122

95123
- name: Checkout fork branch
96124
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
@@ -105,10 +133,10 @@ jobs:
105133
env:
106134
PR_BRANCH: ${{ needs.pr-details.outputs.branch }}
107135
SHA: ${{ needs.pr-details.outputs.sha }}
108-
NGINX_PAT: ${{ steps.secrets.outputs.NGINX_PAT }}
136+
APP_TOKEN: ${{ steps.app_token.outputs.token }}
109137
run: |
110138
git config --global credential.helper store
111-
echo "https://x-access-token:${NGINX_PAT}@github.com" > ~/.git-credentials
139+
echo "https://x-access-token:${APP_TOKEN}@github.com" > ~/.git-credentials
112140
113141
git remote add upstream https://github.com/${{ github.repository }}.git
114142
git fetch upstream
@@ -132,7 +160,7 @@ jobs:
132160
PR_TITLE: ${{ needs.pr-details.outputs.title }}
133161
PR_BODY: ${{ needs.pr-details.outputs.body }}
134162
with:
135-
github-token: ${{ steps.secrets.outputs.NGINX_PAT}}
163+
github-token: ${{ steps.app_token.outputs.token }}
136164
script: |
137165
// Check for existing PR
138166
const { data: existingPRs } = await github.rest.pulls.list({

.github/workflows/publish-helm.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,22 @@ jobs:
140140
- name: Decode GitHub App private key
141141
id: app_key
142142
run: |
143-
private_key=$(echo "$APP_PRIVATE_KEY_B64" | base64 -d | awk 'BEGIN {ORS="\\n"} {print}' | sed 's/\\n$//')
144-
echo "::add-mask::$private_key"
145-
echo "private_key=$private_key" >> "$GITHUB_OUTPUT"
143+
set +x
144+
# Mask the raw base64 value
145+
echo "::add-mask::$APP_PRIVATE_KEY_B64"
146+
private_key=$(printf '%s' "$APP_PRIVATE_KEY_B64" | base64 -d)
147+
# Mask every line of the decoded PEM key individually
148+
while IFS= read -r line; do
149+
if [[ -n "$line" ]]; then
150+
echo "::add-mask::$line"
151+
fi
152+
done <<< "$private_key"
153+
delimiter="GHEOF_$(openssl rand -hex 12)"
154+
{
155+
echo "private_key<<$delimiter"
156+
echo "$private_key"
157+
echo "$delimiter"
158+
} >> "$GITHUB_OUTPUT"
146159
if: ${{ inputs.nginx_helm_repo }}
147160

148161
- name: Generate GitHub App token

.github/workflows/release-pr.yml

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,41 @@ jobs:
109109
tenant-id: ${{ secrets.AZURE_COMMON_VAULT_TENANT_ID }}
110110
subscription-id: ${{ secrets.AZURE_COMMON_VAULT_SUBSCRIPTION_ID }}
111111

112-
- name: Setup secrets
113-
id: secrets
112+
- name: Get secrets from vault
113+
uses: nginx/ci-self-hosted/.github/actions/get-from-vault@5c3e1f8b51f66a851fdba80f70e19cf966199730 # main @ 2026-05-22
114+
with:
115+
vault-name: ${{ secrets.COMMON_KEYVAULT_NAME }}
116+
secret-names: "nginx-bot-nic-create-pr-app-client-id, nginx-bot-nic-create-pr-app-private-key"
117+
env-names: "APP_CLIENT_ID, APP_PRIVATE_KEY_B64"
118+
119+
- name: Decode GitHub App private key
120+
id: app_key
114121
run: |
115-
echo "Setting secrets for job"
116-
NGINX_PAT=$(az keyvault secret show --name nginx-bot-pat --vault-name ${{ secrets.COMMON_KEYVAULT_NAME }} --query value -o tsv)
117-
echo "::add-mask::$NGINX_PAT"
118-
echo "NGINX_PAT=$NGINX_PAT" >> $GITHUB_OUTPUT
122+
set +x
123+
# Mask the raw base64 value
124+
echo "::add-mask::$APP_PRIVATE_KEY_B64"
125+
private_key=$(printf '%s' "$APP_PRIVATE_KEY_B64" | base64 -d)
126+
# Mask every line of the decoded PEM key individually
127+
while IFS= read -r line; do
128+
if [[ -n "$line" ]]; then
129+
echo "::add-mask::$line"
130+
fi
131+
done <<< "$private_key"
132+
delimiter="GHEOF_$(openssl rand -hex 12)"
133+
{
134+
echo "private_key<<$delimiter"
135+
echo "$private_key"
136+
echo "$delimiter"
137+
} >> "$GITHUB_OUTPUT"
138+
139+
- name: Generate GitHub App token
140+
id: app_token
141+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
142+
with:
143+
client-id: ${{ env.APP_CLIENT_ID }}
144+
private-key: ${{ steps.app_key.outputs.private_key }}
145+
owner: ${{ github.repository_owner }}
146+
repositories: ${{ github.event.repository.name }}
119147

120148
- name: Generate secrets for snapshot tests
121149
run: |
@@ -155,7 +183,7 @@ jobs:
155183
- name: Create Pull Request
156184
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
157185
with:
158-
token: ${{ steps.secrets.outputs.NGINX_PAT }}
186+
token: ${{ steps.app_token.outputs.token }}
159187
commit-message: Release ${{ steps.parse.outputs.new_version }}
160188
title: Release ${{ steps.parse.outputs.new_version }}
161189
branch: docs/release-${{ steps.parse.outputs.new_version }}
@@ -206,13 +234,41 @@ jobs:
206234
tenant-id: ${{ secrets.AZURE_COMMON_VAULT_TENANT_ID }}
207235
subscription-id: ${{ secrets.AZURE_COMMON_VAULT_SUBSCRIPTION_ID }}
208236

209-
- name: Setup secrets
210-
id: secrets
237+
- name: Get secrets from vault
238+
uses: nginx/ci-self-hosted/.github/actions/get-from-vault@5c3e1f8b51f66a851fdba80f70e19cf966199730 # main @ 2026-05-22
239+
with:
240+
vault-name: ${{ secrets.COMMON_KEYVAULT_NAME }}
241+
secret-names: "nginx-bot-nic-create-pr-app-client-id, nginx-bot-nic-create-pr-app-private-key"
242+
env-names: "APP_CLIENT_ID, APP_PRIVATE_KEY_B64"
243+
244+
- name: Decode GitHub App private key
245+
id: app_key
211246
run: |
212-
echo "Setting secrets for job"
213-
NGINX_PAT=$(az keyvault secret show --name nginx-bot-pat --vault-name ${{ secrets.COMMON_KEYVAULT_NAME }} --query value -o tsv)
214-
echo "::add-mask::$NGINX_PAT"
215-
echo "NGINX_PAT=$NGINX_PAT" >> $GITHUB_OUTPUT
247+
set +x
248+
# Mask the raw base64 value
249+
echo "::add-mask::$APP_PRIVATE_KEY_B64"
250+
private_key=$(printf '%s' "$APP_PRIVATE_KEY_B64" | base64 -d)
251+
# Mask every line of the decoded PEM key individually
252+
while IFS= read -r line; do
253+
if [[ -n "$line" ]]; then
254+
echo "::add-mask::$line"
255+
fi
256+
done <<< "$private_key"
257+
delimiter="GHEOF_$(openssl rand -hex 12)"
258+
{
259+
echo "private_key<<$delimiter"
260+
echo "$private_key"
261+
echo "$delimiter"
262+
} >> "$GITHUB_OUTPUT"
263+
264+
- name: Generate GitHub App token
265+
id: app_token
266+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
267+
with:
268+
client-id: ${{ env.APP_CLIENT_ID }}
269+
private-key: ${{ steps.app_key.outputs.private_key }}
270+
owner: ${{ github.repository_owner }}
271+
repositories: "${{ github.event.repository.name }},documentation"
216272

217273
- name: Update Documentation Versions
218274
run: |
@@ -230,6 +286,6 @@ jobs:
230286
env:
231287
GITHUB_USERNAME: nginx-bot
232288
GITHUB_EMAIL: integrations@nginx.com
233-
GITHUB_TOKEN: ${{ steps.secrets.outputs.NGINX_PAT }}
289+
GITHUB_TOKEN: ${{ steps.app_token.outputs.token }}
234290
DRY_RUN: ${{ inputs.dry_run && 'true' || 'false' }}
235291
DEBUG: ${{ inputs.debug && 'true' || 'false' }}

0 commit comments

Comments
 (0)