Skip to content

Instantly share code, notes, and snippets.

@ntung
Forked from Xiol/README.md
Created April 13, 2025 08:08
Show Gist options
  • Save ntung/d01dc45013b977dbca2f6f3a265ef27c to your computer and use it in GitHub Desktop.
Save ntung/d01dc45013b977dbca2f6f3a265ef27c to your computer and use it in GitHub Desktop.

Revisions

  1. @Xiol Xiol created this gist May 15, 2024.
    11 changes: 11 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    # Extend Gitlab Access Tokens

    Gitlab [enforced token expiry limits](https://about.gitlab.com/blog/2023/10/25/access-token-lifetime-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](https://python-gitlab.readthedocs.io/en/stable/) 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.
    81 changes: 81 additions & 0 deletions gitlab-token-extend.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    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)