Skip to content

Commit bc9cccd

Browse files
committed
feat: add scrit to renew api-token for gitlab
Signed-off-by: sebastien.heurtematte <[email protected]>
1 parent c39de6a commit bc9cccd

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed

gitlab/gitlab_admin.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,47 @@ create_api_token() {
227227
echo "${token}"
228228
}
229229

230+
check_api_token_validity() {
231+
local username="${1:-}"
232+
_check_parameter "username" "${username}"
233+
local user_id
234+
user_id="$(_get_id_from_username "${username}")"
235+
local name="CI token"
236+
237+
impersonation_tokens=$(curl -sSL --header "${TOKEN_HEADER}" \
238+
"${API_BASE_URL}/users/${user_id}/impersonation_tokens?per_page=100")
239+
240+
check_error=$(echo "$impersonation_tokens" | jq -c '.error' 2>/dev/null) || true
241+
if [[ -n "${check_error}" ]]; then
242+
echo "Error: ${check_error}"
243+
exit 1
244+
fi
245+
246+
expired=true
247+
expires_at=""
248+
# Vérifier chaque token
249+
for token in $(echo "$impersonation_tokens" | jq -c '.[]'); do
250+
name=$(echo "$token" | jq -r '.name')
251+
if [ "$name" == "CI token" ]; then
252+
revoked=$(echo "$token" | jq -r '.revoked')
253+
active=$(echo "$token" | jq -r '.active')
254+
expires_at=$(echo "$token" | jq -r '.expires_at')
255+
256+
# echo "Revoked: $revoked - Active: $active - Expires at: $expires_at"
257+
258+
if [[ "$active" == "true" ]] && [[ "$revoked" == "false" ]]; then
259+
expired=false
260+
fi
261+
fi
262+
done
263+
if [ "$expired" == "true" ]; then
264+
echo "CI Token ${username}(${user_id}) expired or revoked: $expires_at"
265+
exit 1
266+
else
267+
echo "CI Token ${username}(${user_id}) is still valid, expired: $expires_at"
268+
fi
269+
}
270+
230271
create_bot_user() {
231272
local project_name="${1:-}"
232273
local username="${2:-}"

gitlab/gitlab_bot_token_renew.sh

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#!/usr/bin/env bash
2+
#*******************************************************************************
3+
# Copyright (c) 2024 Eclipse Foundation and others.
4+
# This program and the accompanying materials are made available
5+
# under the terms of the Eclipse Public License 2.0
6+
# which is available at http://www.eclipse.org/legal/epl-v20.html
7+
# SPDX-License-Identifier: EPL-2.0
8+
#*******************************************************************************
9+
10+
# Create bot user in GitLab and set up SSH key
11+
12+
# Bash strict-mode
13+
# set -o errexit
14+
set -o nounset
15+
set -o pipefail
16+
17+
IFS=$'\n\t'
18+
SCRIPT_FOLDER="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
19+
CI_ADMIN_ROOT="${SCRIPT_FOLDER}/.."
20+
JIRO_ROOT_FOLDER="$("${CI_ADMIN_ROOT}/utils/local_config.sh" "get_var" "jiro-root-dir")"
21+
OTTERDOG_CONFIGS_ROOT="$("${CI_ADMIN_ROOT}/utils/local_config.sh" "get_var" "otterdog-configs-root-dir")"
22+
GITLAB_PASS_DOMAIN="gitlab.eclipse.org"
23+
24+
#shellcheck disable=SC1091
25+
source "${SCRIPT_FOLDER}/../pass/pass_wrapper.sh"
26+
#shellcheck disable=SC1091
27+
source "${SCRIPT_FOLDER}/../utils/common.sh"
28+
29+
set +o errexit
30+
31+
export VAULT_ADDR=${VAULT_ADDR:-https:\/\/secretsmanager.eclipse.org}
32+
export VAULT_AUTH_METHOD=${VAULT_AUTH_METHOD:-token}
33+
export VAULT_TOKEN=${VAULT_TOKEN:-""}
34+
35+
VAULT_MOUNT_PATH="cbi"
36+
37+
usage() {
38+
cat << EOF # remove the space between << and EOF, this is due to web plugin issue
39+
Usage: $(basename "${BASH_SOURCE[0]}") <project_id> [-h] [-v] [-f]
40+
41+
Renew GitLab API token for the bot user of the project <project_id> or all projects bots registered in the secretsmanager.
42+
43+
Available options:
44+
45+
-h Help
46+
-v Verbose mode
47+
48+
# Script params:
49+
-f FORCE_UPDATE: Force update tools for the project
50+
51+
EOF
52+
exit
53+
}
54+
55+
FORCE_UPDATE=""
56+
PARAM=${1:-}
57+
58+
if [[ -n "${PARAM}" ]] && [[ "${PARAM}" =~ ^- ]]; then
59+
OPTIND=1
60+
else
61+
OPTIND=2
62+
fi
63+
64+
while getopts ":hvf" option; do
65+
case $option in
66+
h) usage ;;
67+
v) set -x ;;
68+
f)
69+
FORCE_UPDATE="true"
70+
;;
71+
:)
72+
echo "ERROR: the option -$OPTARG need an argument." >&2
73+
exit 1
74+
;;
75+
-?*) echo "Unknown option: $1" && exit 1 ;;
76+
*) break ;;
77+
esac
78+
done
79+
80+
if ! vault token lookup > /dev/null; then
81+
echo "Check your token validity and export VAULT_TOKEN"
82+
exit 1
83+
fi
84+
85+
if ! vault kv list -mount="${VAULT_MOUNT_PATH}" > /dev/null; then
86+
echo "Error accessing the secret mount: ${VAULT_MOUNT_PATH}}"
87+
exit 1
88+
fi
89+
90+
if [[ ${FORCE_UPDATE} == "true" ]]; then
91+
echo "WARN: Force update tools"
92+
fi
93+
94+
# Renew all tokens for all projects registered in Vault
95+
renew_all_tokens() {
96+
projects=$(vault kv list -mount="${VAULT_MOUNT_PATH}" -format=json)
97+
if [ "$?" -ne 0 ]; then
98+
echo "ERROR: listing secrets at mount: ${VAULT_MOUNT_PATH}}"
99+
return 1
100+
fi
101+
for project in $(echo "${projects}" | jq -r '.[]'); do
102+
local project_id="${project%/}"
103+
renew_token "${project_id}"
104+
done
105+
}
106+
107+
# Check if the API token is still valid and renew it if necessary
108+
renew_token() {
109+
local project_id="${1:-}"
110+
echo "############### Check project: ${project_id} ###############"
111+
token=$(vault kv get -mount="${VAULT_MOUNT_PATH}" -field="api-token" "${project_id}/gitlab.eclipse.org" 2>/dev/null) || true
112+
if [ -n "$token" ]; then
113+
username=$(vault kv get -mount="${VAULT_MOUNT_PATH}" -field="username" "${project_id}/gitlab.eclipse.org" 2>/dev/null) || true
114+
if "${SCRIPT_FOLDER}/gitlab_admin.sh" check_api_token_validity "${username}"; then
115+
if [[ -z "${FORCE_UPDATE}" ]]; then
116+
force_update=$(_question_true_false "Force update tools for ${project_id}")
117+
if [[ "$force_update" == "true" ]];then
118+
update_tools "${project_id}"
119+
fi
120+
elif [[ "${FORCE_UPDATE}" == "true" ]]; then
121+
update_tools "${project_id}"
122+
else
123+
echo "No tools update for ${project_id}"
124+
fi
125+
else
126+
create_token "${project_id}" "${username}"
127+
update_tools "${project_id}"
128+
fi
129+
else
130+
echo "No GitLab token found for ${project_id}"
131+
fi
132+
}
133+
134+
update_tools() {
135+
local project_id="${1:-}"
136+
if [[ -z "${project_id}" ]]; then
137+
echo "No project_id provided"
138+
return 1
139+
fi
140+
update_jenkins "${project_id}"
141+
update_otterdog "${project_id}"
142+
}
143+
144+
# Create a new API token for the bot user
145+
create_token() {
146+
local project_id="${1:-}"
147+
local username="${2:-}"
148+
token="$("${SCRIPT_FOLDER}/gitlab_admin.sh" "create_api_token" "${username}")"
149+
echo "Adding API token to pass: bots/${project_id}/${GITLAB_PASS_DOMAIN}/api-token"
150+
echo "${token}" | passw cbi insert --echo "bots/${project_id}/${GITLAB_PASS_DOMAIN}/api-token"
151+
}
152+
153+
# Update Jenkins configuration
154+
update_jenkins() {
155+
local project_id="${1:-}"
156+
if [[ -d "${JIRO_ROOT_FOLDER}/instances/${project_id}" ]]; then
157+
echo "Recreate token in Jenkins instance for ${project_id}"
158+
"${JIRO_ROOT_FOLDER}/jenkins-create-credentials-token.sh" "gitlab" "${project_id}"
159+
"${JIRO_ROOT_FOLDER}/jenkins-create-credentials-token.sh" "gitlab_pat" "${project_id}"
160+
else
161+
echo "No Jenkins instance found for ${project_id}"
162+
fi
163+
}
164+
165+
# Update Otterdog configuration
166+
update_otterdog() {
167+
local project_id="${1:-}"
168+
local short_name="${project_id##*.}"
169+
pushd "${OTTERDOG_CONFIGS_ROOT}" > /dev/null
170+
find=$(jq --arg project_id "$project_id" '.organizations[] | select(.name == $project_id)' < otterdog.json)
171+
if [[ -n "${find}" ]]; then
172+
echo "Update token with Otterdog for eclipse-${short_name} - ${project_id}"
173+
PASSWORD_STORE_DIR="$("${SCRIPT_FOLDER}/../utils/local_config.sh" "get_var" "cbi-dir" "password-store")"
174+
export PASSWORD_STORE_DIR
175+
otterdog fetch-config -f "eclipse-${short_name}"
176+
otterdog apply -f "eclipse-${short_name}" -n --update-secrets --update-filter "*GITLAB_API_TOKEN"
177+
else
178+
echo "No Otterdog configuration found for ${project_id}"
179+
fi
180+
popd > /dev/null
181+
}
182+
183+
if [[ -z "${PARAM}" || "${PARAM}" =~ ^- ]]; then
184+
renew_all_tokens
185+
else
186+
renew_token "${PARAM}"
187+
fi
188+

0 commit comments

Comments
 (0)