Skip to content

Instantly share code, notes, and snippets.

@Xiol
Last active July 18, 2024 19:34
Show Gist options
  • Save Xiol/426e6cd08942d77ef6a1657f8673a2a0 to your computer and use it in GitHub Desktop.
Save Xiol/426e6cd08942d77ef6a1657f8673a2a0 to your computer and use it in GitHub Desktop.
Extend Gitlab access token expiry dates

Extend Gitlab Access Tokens

Gitlab enforced token expiry limits to 365 days last year, and the time is now upon us.

They don't have an opt-out for this, and haven't provided a way to easily extend tokens in the web interface. They have also gated their credential management interface behind their Ultimate license.

This quickly thrown together script will allow you to add an extra year to all tokens that expire in the next 30 days. It will not reactivate tokens that have already expired.

Requires the python-gitlab module. Edit your self-hosted Gitlab instance details into the script and run it. It will dump out CSVs of all expiring tokens, and then dump out a list of commands you can paste into a gitlab-rails console session to extend the expiry date by another year. If you need them to be active for longer, change 1.year.from_now to the value of your choice, e.g. 10.years.from_now.

Rotating your tokens is the right thing to do, but sometimes you just need more time.

import os
import sys
import gitlab
import datetime
token = os.environ.get('GITLAB_ACCESS_TOKEN', None)
if token is None:
print("Please set GITLAB_ACCESS_TOKEN")
sys.exit(1)
gl = gitlab.Gitlab('https://YOUR-GITLAB-INSTANCE.co.uk', private_token=token, user_agent='token_checker/0.1')
todayplus30 = (datetime.datetime.today() + datetime.timedelta(days=30)).strftime('%Y-%m-%d')
commands = []
print("PAT")
print("user,token_id,token_name,expires_at")
for t in gl.personal_access_tokens.list(all=True, as_list=False):
if t.revoked or not t.active:
continue
if t.expires_at is not None:
if t.expires_at <= todayplus30:
user = gl.users.get(t.user_id)
if user.state != "active":
continue
print(f'"{user.name}","{t.id}","{t.name}","{t.expires_at}"')
commands.append(f"PersonalAccessToken.where(id: {t.id}).update_all(expires_at: 1.year.from_now)")
print()
print()
print("GROUP TOKENS")
print("group,group_id,token_id,token_name,expires_at")
for group in gl.groups.list(all=True, as_list=False):
for t in group.access_tokens.list(all=True, as_list=False):
if t.revoked or not t.active:
continue
if t.expires_at is not None:
if t.expires_at <= todayplus30:
print(f'"{group.name}","{group.id}","{t.id}","{t.name}","{t.expires_at}"')
# Group tokens still appear as PATs
commands.append(f"PersonalAccessToken.where(id: {t.id}).update_all(expires_at: 1.year.from_now)")
print()
print()
print("PROJECT TOKENS")
print("project,project_id,token_id,token_name,expires_at")
for project in gl.projects.list(all=True, as_list=False):
for t in project.access_tokens.list(all=True, as_list=False):
if t.revoked or not t.active:
continue
if t.expires_at is not None:
if t.expires_at <= todayplus30:
print(f'"{project.name}","{project.id}","{t.id}","{t.name}","{t.expires_at}"')
# Project tokens are also PATs, woo
commands.append(f"PersonalAccessToken.where(id: {t.id}).update_all(expires_at: 1.year.from_now)")
# Deploy tokens don't currently appear to have enforce expiry dates, so skip those.
# print()
# print()
# print("DEPLOY TOKENS")
# print("deploy_token_id,deploy_token_name,deploy_token_username,expires_at")
# for t in gl.deploytokens.list(all=True, as_list=False):
# if t.revoked or t.expired:
# continue
# if t.expires_at is not None:
# if t.expires_at <= todayplus30:
# print(f'"{t.id}","{t.name}","{t.username}","{t.expires_at}"')
print()
print()
print("COMMANDS")
print("These are the commands to extend the expiration date of the tokens.")
print("On the Gitlab server run `gitlab-rails console` and paste these commands in.")
print()
for c in commands:
print(c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment