Skip to content

Commit 65b7cd0

Browse files
Create rotate_sonar_token.yml
1 parent b5bf7ac commit 65b7cd0

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Rotate Sonar Token
2+
3+
on:
4+
schedule:
5+
- cron: "0 6 1 */3 *"
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
actions: write
11+
12+
jobs:
13+
rotate:
14+
runs-on: ubuntu-latest
15+
env:
16+
SQ_URL: ${{ secrets.SONAR_HOST_URL }}
17+
SQ_TOKEN: ${{ secrets.SONAR_ROTATOR_TOKEN }}
18+
PROJECT_KEY: singnet_snet-dapp_df2bdd78-17f8-467d-a908-74e4c0758f08
19+
SECRET_NAME: SONAR_TOKEN
20+
steps:
21+
- name: Install jq and gh
22+
run: |
23+
set -euo pipefail
24+
sudo apt-get update -y
25+
sudo apt-get install -y jq
26+
gh --version
27+
28+
- name: Sanity check
29+
run: |
30+
set -euo pipefail
31+
BASE="${SQ_URL%/}"; BASE="${BASE%%/api*}"
32+
RESP=$(curl -sS -H "Authorization: Bearer $SQ_TOKEN" -H "Accept: application/json" \
33+
"$BASE/api/authentication/validate")
34+
echo "$RESP" | grep -q '"valid"[[:space:]]*:[[:space:]]*true' || { echo "Auth validate failed: $RESP"; exit 1; }
35+
36+
- name: Generate Project Analysis Token
37+
id: gen
38+
run: |
39+
set -euo pipefail
40+
BASE="${SQ_URL%/}"; BASE="${BASE%%/api*}"
41+
LABEL="${PROJECT_KEY}-ci-$(date +%Y%m%d%H%M%S)"
42+
BODY=$(mktemp)
43+
HDR=$(mktemp)
44+
CODE=$(curl -sS -L -D "$HDR" -o "$BODY" -w "%{http_code}" \
45+
-H "Authorization: Bearer $SQ_TOKEN" \
46+
-H "Accept: application/json" \
47+
-X POST "$BASE/api/user_tokens/generate" \
48+
--data-urlencode "name=$LABEL" \
49+
--data-urlencode "type=PROJECT_ANALYSIS_TOKEN" \
50+
--data-urlencode "projectKey=$PROJECT_KEY")
51+
echo "HTTP $CODE"
52+
CT=$(grep -i '^content-type:' "$HDR" | head -n1 || true)
53+
echo "Content-Type: ${CT:-<none>}"
54+
echo "$CT" | grep -qi 'application/json' || { echo "Non-JSON body head:"; head -c 400 "$BODY" || true; echo; exit 1; }
55+
NEW_TOKEN=$(jq -r '.token // empty' "$BODY")
56+
[ -n "$NEW_TOKEN" ] || { echo "No .token field. Body head:"; head -c 400 "$BODY" || true; echo; exit 1; }
57+
echo "token=$NEW_TOKEN" >> "$GITHUB_OUTPUT"
58+
59+
- name: Get GitHub App token
60+
id: app-token
61+
uses: actions/create-github-app-token@v1
62+
with:
63+
app-id: ${{ secrets.SNET_SONARQUBE_APP_ID }}
64+
private-key: ${{ secrets.SNET_SONARQUBE_APP_KEY }}
65+
66+
- name: Debug App token
67+
env:
68+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
69+
run: |
70+
set -e
71+
echo "== Auth status =="
72+
gh auth status
73+
echo "== Repo info =="
74+
gh api repos/$GITHUB_REPOSITORY --jq '.full_name, .permissions'
75+
echo "== Try secrets public-key =="
76+
gh api repos/$GITHUB_REPOSITORY/actions/secrets/public-key || true
77+
78+
- name: Update repo secret with App token
79+
env:
80+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
81+
run: |
82+
echo "${{ steps.gen.outputs.token }}" | gh secret set "$SECRET_NAME" --repo "$GITHUB_REPOSITORY"
83+
echo "Updated $SECRET_NAME"
84+
85+
- name: Revoke old tokens older than 120 days
86+
run: |
87+
set -euo pipefail
88+
BASE="${SQ_URL%/}"; BASE="${BASE%%/api*}"
89+
NOW=$(date +%s)
90+
91+
# Find the latest token so we never accidentally revoke it
92+
LATEST=$(curl -sS -H "Authorization: Bearer $SQ_TOKEN" "$BASE/api/user_tokens/search" \
93+
| jq -r '.userTokens[] | select(.name | test("'"$PROJECT_KEY"'-ci-")) | .name' \
94+
| head -n1)
95+
96+
curl -sS -H "Authorization: Bearer $SQ_TOKEN" "$BASE/api/user_tokens/search" \
97+
| jq -r '.userTokens[] | "\(.name)|\(.creationDate)"' \
98+
| while IFS='|' read -r NAME DATE; do
99+
case "$NAME" in
100+
${PROJECT_KEY}-ci-*)
101+
if [ "$NAME" = "$LATEST" ]; then
102+
echo "Skipping the latest token $NAME"
103+
continue
104+
fi
105+
106+
TS=$(date -d "$DATE" +%s 2>/dev/null || echo 0)
107+
if [ "$TS" -eq 0 ]; then
108+
echo "Could not parse date $DATE for $NAME, skipping"
109+
continue
110+
fi
111+
112+
AGE=$(( (NOW-TS)/86400 ))
113+
if [ "$AGE" -gt 120 ]; then
114+
curl -sS -H "Authorization: Bearer $SQ_TOKEN" \
115+
-X POST "$BASE/api/user_tokens/revoke" \
116+
--data-urlencode "name=$NAME" >/dev/null
117+
echo "Revoked $NAME (age ${AGE}d)"
118+
fi
119+
;;
120+
esac
121+
done

0 commit comments

Comments
 (0)