From cc1fd098057d1326cdb333bef9834895fa0925e5 Mon Sep 17 00:00:00 2001 From: "Hahn Axel (hahn)" <axel.hahn@unibe.ch> Date: Fri, 25 Oct 2024 17:13:01 +0200 Subject: [PATCH] WIP check gitlab tokens --- check_gitlab_tokens | 237 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100755 check_gitlab_tokens diff --git a/check_gitlab_tokens b/check_gitlab_tokens new file mode 100755 index 0000000..9b4ca1f --- /dev/null +++ b/check_gitlab_tokens @@ -0,0 +1,237 @@ +#!/bin/bash +# ====================================================================== +# +# Check Gitlab tokens +# +# requirements: +# - inc/rest-api-client.sh +# - curl +# +# ---------------------------------------------------------------------- +# 2024-10-25 v0.0 <axel.hahn@iml.unibe.ch> +# ====================================================================== + + +cd "$( dirname "$0" )" || exit + +. "$( dirname $0 )/inc_pluginfunctions" || exit 1 + +export self_APPVERSION=0.1 + +GITLAB_API='https://gitlab.example.com/api/v4' +GITLAB_TOKEN='glpat-12345678' + +GITLAB_API='https://git-repo.iml.unibe.ch/api/v4' +GITLAB_TOKEN='glpat-4Lh6j_aJv7b6zVsRxyXF' + +GITLAB_CONFIG=/etc/icinga2/gitlab.cfg +REST_CLIENT="$( dirname $0 )/../inc/rest-api-client.sh" + +typeset -i iSince=395 +typeset -i iTokenCount +typeset -i iTokensFound +NL=" +" + +typeset -i iWarnLimit=300 +typeset -i iCriticalLimit=200 + +typeset -i iCountWarn=0 +typeset -i iCountCritical=0 +output="" + +# ---------------------------------------------------------------------- +# functions +# ---------------------------------------------------------------------- + + +function showHelp(){ + local _self; _self=$(basename $0) +cat <<EOF +$( ph.showImlHelpHeader ) + +Check gitlab tokens and warn if a token expires soon. + +This check fetches the gitlbab tokens created in the last $iSince days +from the Gitlab API. It skips + + - personal access tokens of users + - revoked tokens + +SYNTAX: +$_self [-w WARN_LIMIT] [-c CRITICAL_LIMIT] + +OPTIONS: + + -h or --help show this help. + + -w VALUE warning level (default: $iWarnLimit) + -c VALUE critical level (default: $iCriticalLimit) + + -g FILE path to GITLAB_CONFIG; default: $GITLAB_CONFIG + -r FILE path to REST_CLIENT; default: $REST_CLIENT + + -s DAYS Number of days for max age of token; default: $iSince + +PARAMETERS: + + None. + +EXAMPLE: + $(basename $0) -w 28 -c 7 + +EOF +} + +# Ffetch data from gitlab api with page requests +# param string url +# param string output file +# param int optional: number of items per page; default: 100 +function _getPagesToFile(){ + local url="$1" + local outfile="$2" + local iPerPage=${3:-100} + local page=0 + + test -f "${outfile}" && rm "${outfile}" + + grep -q "?" <<< "$url" || url="${url}?" + while true; do + (( page++ )) + + pageUrl="$url&per_page=${iPerPage}&page=${page}" + # echo "Request: $pageUrl" + + http.makeRequest "$pageUrl" + if ! http.isOk > /dev/null; then + echo "ERROR: Request failed: $pageUrl" + http.getResponseHeader + http.getResponse + exit 1 + fi + + # if response is "[]" then we are done + if ! http.getResponse | grep -q "^\[\]$"; then + http.getResponse >> "${outfile}" + else + break + fi + + done +} + +function getKey(){ + echo "$1" | jq -r ".$2" | grep -v "null" +} + +# ---------------------------------------------------------------------- +# MAIN +# ---------------------------------------------------------------------- + +# --- check param -h +case "$1" in + "--help"|"-h") + showHelp + exit 0 + ;; + *) +esac + +REST_CLIENT=$( ph.getValueWithParam $REST_CLIENT r "$@") +GITLAB_CONFIG=$( ph.getValueWithParam $GITLAB_CONFIG g "$@") + +# --- check requirements +ph.require curl +. "${GITLAB_CONFIG}" || exit 1 +. "${REST_CLIENT}" || exit 1 +http.help >/dev/null || exit 1 + + +iWarnLimit=$( ph.getValueWithParam $iWarnLimit w "$@") +iCriticalLimit=$( ph.getValueWithParam $iCriticalLimit c "$@") +iSince=$( ph.getValueWithParam $iSince s "$@") + +http.init +http.addHeader "PRIVATE-TOKEN: $GITLAB_TOKEN" +http.setBaseUrl "$GITLAB_API" + +startdate="$( date +%Y-%m-%dT00:00:00Z --date "$iSince days ago")" +sDateWarn="$( date +%Y%m%d --date "${iWarnLimit} days" )" +sDateCritical="$( date +%Y%m%d --date "${iCriticalLimit} days" )" + +url="/personal_access_tokens/?revoked=false&created_after=${startdate}" +_getPagesToFile "$url" "/tmp/gitlab-tokens.json" +_getPagesToFile "/users" /tmp/gitlab-users.json + + +# IDs / Einträge zählen: +iTokenCount=$( cat /tmp/gitlab-tokens.json | jq ".[].id " | wc -l ) +# echo "Found Tokens since $startdate: $iTokenCount" + + +# echo "Warn when expiring before: ${sDateWarn} ... critical before: ${sDateCritical}" +# loop over tokens + +iTokensFound=0 + +for i in $( seq 1 $iTokenCount ) +do + + # get nth token + entry="$( cat /tmp/gitlab-tokens.json | jq ".[$i]" )" + + # hide non active tokens + if [ "$( getKey "$entry" "active" )" = "false" ]; then + continue + fi + + # hide tokens without name + sName=$( getKey "$entry" "name" ) + if [ -z "$sName" ]; then + continue + fi + + # hide tokens referencing a username that doesn't contain "_[number]_bot_" + sUserid=$( getKey "$entry" "user_id" ) + myusername="$( cat /tmp/gitlab-users.json | jq ".[] | select(.id == $sUserid)" | jq ".username" | cut -f 1-3 -d "_" | tr -d '"') " + if ! grep -q "_[0-9]*_bot" <<< "$myusername" ; then + continue + fi + + iTokensFound+=1 + + # check expiration + sExpire=$( getKey "$entry" "expires_at" ) + + # remove "-" from date to get an integer + sExpire2=${sExpire//\-} + + + sStatus="OK " + if [ "$sExpire2" -le "$sDateWarn" ]; then + if [ "$sExpire2" -le "$sDateCritical" ]; then + iCountCritical+=1 + sStatus="Critical" + else + iCountWarn+=1 + sStatus="Warning " + fi + fi + + output+="$sExpire $sStatus $sName $myusername${NL}" + +done + +if [ $iCountCritical -gt 0 ]; then + ph.setStatus "critical" +elif [ $iCountWarn -gt 0 ]; then + ph.setStatus "warning" +else + ph.setStatus "ok" +fi + +ph.status "$iTokensFound Gitlab Tokens (max $iSince days old) .. critical: $iCountCritical ($iCriticalLimit days) .. warnings: $iCountWarn ($iWarnLimit days)" +echo + +echo "$output" +rm -f /tmp/gitlab-tokens.json /tmp/gitlab-users.json \ No newline at end of file -- GitLab