Skip to content

Commit

Permalink
feat: add scrit to renew api-token for gitlab
Browse files Browse the repository at this point in the history
Signed-off-by: sebastien.heurtematte <[email protected]>
  • Loading branch information
heurtematte committed Sep 11, 2024
1 parent c39de6a commit bc9cccd
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
41 changes: 41 additions & 0 deletions gitlab/gitlab_admin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,47 @@ create_api_token() {
echo "${token}"
}

check_api_token_validity() {
local username="${1:-}"
_check_parameter "username" "${username}"
local user_id
user_id="$(_get_id_from_username "${username}")"
local name="CI token"

impersonation_tokens=$(curl -sSL --header "${TOKEN_HEADER}" \
"${API_BASE_URL}/users/${user_id}/impersonation_tokens?per_page=100")

check_error=$(echo "$impersonation_tokens" | jq -c '.error' 2>/dev/null) || true
if [[ -n "${check_error}" ]]; then
echo "Error: ${check_error}"
exit 1
fi

expired=true
expires_at=""
# Vérifier chaque token
for token in $(echo "$impersonation_tokens" | jq -c '.[]'); do
name=$(echo "$token" | jq -r '.name')
if [ "$name" == "CI token" ]; then
revoked=$(echo "$token" | jq -r '.revoked')
active=$(echo "$token" | jq -r '.active')
expires_at=$(echo "$token" | jq -r '.expires_at')

# echo "Revoked: $revoked - Active: $active - Expires at: $expires_at"

if [[ "$active" == "true" ]] && [[ "$revoked" == "false" ]]; then
expired=false
fi
fi
done
if [ "$expired" == "true" ]; then
echo "CI Token ${username}(${user_id}) expired or revoked: $expires_at"
exit 1
else
echo "CI Token ${username}(${user_id}) is still valid, expired: $expires_at"
fi
}

create_bot_user() {
local project_name="${1:-}"
local username="${2:-}"
Expand Down
188 changes: 188 additions & 0 deletions gitlab/gitlab_bot_token_renew.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#!/usr/bin/env bash
#*******************************************************************************
# Copyright (c) 2024 Eclipse Foundation and others.
# This program and the accompanying materials are made available
# under the terms of the Eclipse Public License 2.0
# which is available at http://www.eclipse.org/legal/epl-v20.html
# SPDX-License-Identifier: EPL-2.0
#*******************************************************************************

# Create bot user in GitLab and set up SSH key

# Bash strict-mode
# set -o errexit
set -o nounset
set -o pipefail

IFS=$'\n\t'
SCRIPT_FOLDER="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
CI_ADMIN_ROOT="${SCRIPT_FOLDER}/.."
JIRO_ROOT_FOLDER="$("${CI_ADMIN_ROOT}/utils/local_config.sh" "get_var" "jiro-root-dir")"
OTTERDOG_CONFIGS_ROOT="$("${CI_ADMIN_ROOT}/utils/local_config.sh" "get_var" "otterdog-configs-root-dir")"
GITLAB_PASS_DOMAIN="gitlab.eclipse.org"

#shellcheck disable=SC1091
source "${SCRIPT_FOLDER}/../pass/pass_wrapper.sh"
#shellcheck disable=SC1091
source "${SCRIPT_FOLDER}/../utils/common.sh"

set +o errexit

export VAULT_ADDR=${VAULT_ADDR:-https:\/\/secretsmanager.eclipse.org}
export VAULT_AUTH_METHOD=${VAULT_AUTH_METHOD:-token}
export VAULT_TOKEN=${VAULT_TOKEN:-""}

VAULT_MOUNT_PATH="cbi"

usage() {
cat << EOF # remove the space between << and EOF, this is due to web plugin issue
Usage: $(basename "${BASH_SOURCE[0]}") <project_id> [-h] [-v] [-f]
Renew GitLab API token for the bot user of the project <project_id> or all projects bots registered in the secretsmanager.
Available options:
-h Help
-v Verbose mode
# Script params:
-f FORCE_UPDATE: Force update tools for the project
EOF
exit
}

FORCE_UPDATE=""
PARAM=${1:-}

if [[ -n "${PARAM}" ]] && [[ "${PARAM}" =~ ^- ]]; then
OPTIND=1
else
OPTIND=2
fi

while getopts ":hvf" option; do
case $option in
h) usage ;;
v) set -x ;;
f)
FORCE_UPDATE="true"
;;
:)
echo "ERROR: the option -$OPTARG need an argument." >&2
exit 1
;;
-?*) echo "Unknown option: $1" && exit 1 ;;
*) break ;;
esac
done

if ! vault token lookup > /dev/null; then
echo "Check your token validity and export VAULT_TOKEN"
exit 1
fi

if ! vault kv list -mount="${VAULT_MOUNT_PATH}" > /dev/null; then
echo "Error accessing the secret mount: ${VAULT_MOUNT_PATH}}"
exit 1
fi

if [[ ${FORCE_UPDATE} == "true" ]]; then
echo "WARN: Force update tools"
fi

# Renew all tokens for all projects registered in Vault
renew_all_tokens() {
projects=$(vault kv list -mount="${VAULT_MOUNT_PATH}" -format=json)
if [ "$?" -ne 0 ]; then
echo "ERROR: listing secrets at mount: ${VAULT_MOUNT_PATH}}"
return 1
fi
for project in $(echo "${projects}" | jq -r '.[]'); do
local project_id="${project%/}"
renew_token "${project_id}"
done
}

# Check if the API token is still valid and renew it if necessary
renew_token() {
local project_id="${1:-}"
echo "############### Check project: ${project_id} ###############"
token=$(vault kv get -mount="${VAULT_MOUNT_PATH}" -field="api-token" "${project_id}/gitlab.eclipse.org" 2>/dev/null) || true
if [ -n "$token" ]; then
username=$(vault kv get -mount="${VAULT_MOUNT_PATH}" -field="username" "${project_id}/gitlab.eclipse.org" 2>/dev/null) || true
if "${SCRIPT_FOLDER}/gitlab_admin.sh" check_api_token_validity "${username}"; then
if [[ -z "${FORCE_UPDATE}" ]]; then
force_update=$(_question_true_false "Force update tools for ${project_id}")
if [[ "$force_update" == "true" ]];then
update_tools "${project_id}"
fi
elif [[ "${FORCE_UPDATE}" == "true" ]]; then
update_tools "${project_id}"
else
echo "No tools update for ${project_id}"
fi
else
create_token "${project_id}" "${username}"
update_tools "${project_id}"
fi
else
echo "No GitLab token found for ${project_id}"
fi
}

update_tools() {
local project_id="${1:-}"
if [[ -z "${project_id}" ]]; then
echo "No project_id provided"
return 1
fi
update_jenkins "${project_id}"
update_otterdog "${project_id}"
}

# Create a new API token for the bot user
create_token() {
local project_id="${1:-}"
local username="${2:-}"
token="$("${SCRIPT_FOLDER}/gitlab_admin.sh" "create_api_token" "${username}")"
echo "Adding API token to pass: bots/${project_id}/${GITLAB_PASS_DOMAIN}/api-token"
echo "${token}" | passw cbi insert --echo "bots/${project_id}/${GITLAB_PASS_DOMAIN}/api-token"
}

# Update Jenkins configuration
update_jenkins() {
local project_id="${1:-}"
if [[ -d "${JIRO_ROOT_FOLDER}/instances/${project_id}" ]]; then
echo "Recreate token in Jenkins instance for ${project_id}"
"${JIRO_ROOT_FOLDER}/jenkins-create-credentials-token.sh" "gitlab" "${project_id}"
"${JIRO_ROOT_FOLDER}/jenkins-create-credentials-token.sh" "gitlab_pat" "${project_id}"
else
echo "No Jenkins instance found for ${project_id}"
fi
}

# Update Otterdog configuration
update_otterdog() {
local project_id="${1:-}"
local short_name="${project_id##*.}"
pushd "${OTTERDOG_CONFIGS_ROOT}" > /dev/null
find=$(jq --arg project_id "$project_id" '.organizations[] | select(.name == $project_id)' < otterdog.json)
if [[ -n "${find}" ]]; then
echo "Update token with Otterdog for eclipse-${short_name} - ${project_id}"
PASSWORD_STORE_DIR="$("${SCRIPT_FOLDER}/../utils/local_config.sh" "get_var" "cbi-dir" "password-store")"
export PASSWORD_STORE_DIR
otterdog fetch-config -f "eclipse-${short_name}"
otterdog apply -f "eclipse-${short_name}" -n --update-secrets --update-filter "*GITLAB_API_TOKEN"
else
echo "No Otterdog configuration found for ${project_id}"
fi
popd > /dev/null
}

if [[ -z "${PARAM}" || "${PARAM}" =~ ^- ]]; then
renew_all_tokens
else
renew_token "${PARAM}"
fi

0 comments on commit bc9cccd

Please sign in to comment.