GitLab Access Token Updater/Rotation Manager
This app addresses the following challenges:
- Token Expiration Management: If you've created numerous Group/Project Access Tokens without expiration dates, these tokens can unexpectedly become a problem once got expired (broken automation, pipeline, etc), as outlined in GitLab's new expiration policy.
- Premium Solution Limitations: GitLab Premium or Ultimate users are recommended to use Service Account personal access tokens that don’t expire (mentioned in blog above). However, this introduces additional security risks.
- Service Account Management: Not a direct issue, managing Service Accounts is difficult due to the lack of a UI, as noted in GitLab's current limitations, requiring manual API calls for management.
- Token Usage Visibility: Tracking Group/Project access token usage is limited, and rotating or renewing tokens requires locating and updating each token’s use, such as in CI/CD or Kubernetes secrets.
- Response to Token Leaks or Staff Changes: When tokens are leaked or an employee leaves, the lack of visibility or automation around access tokens makes you don't want rotate it.
Installation
Docker
Assuming your main configuration file is located in the current directory:
docker run -v `./config.yml:/tmp/config.yml` -it --rm iomarmochtar/gitlab-token-updater:latest -c /tmp/config.yml
Compiled
Go to the releases page for a compiled version specific to your OS and architecture.
Source Build
Ensure to have following package installed on your local:
Run following commands:
git clone https://github.com/iomarmochtar/gitlab-token-updater.git
cd gitlab-token-updater
make dist-dev
the compiled binary is located under folder dist
How To Use
Preparations
1. Personal Access Token
As Group/Project Access Tokens cannot be used to create other access token related to the access token rotation API (example), use a Personal Access Token for access token rotation.
Create a Personal Access Token with the api scope. You may also create another with the read_api scope for MR dry run purposes.
2. Config File
To run the application, specify the configuration file with the -c
or --config
argument. Other modes are available.
Execution
For the normal execution, just poin the configuration file with argument -c
or --config
, some of other modes are available
gitlab-token-updater -c [PATH_TO_CONFIG_FILE]
Mode
You can enable each mode by adding the respective argument, and they can be used in combination.
If any error occurs during execution, it will not interrupt the iteration; errors are accumulated and reported at the end. This behavior can be modified by running in strict mode.
Dry Run
Run with the --dry-run
argument. This will execute read-only APIs and verify the existence of specified objects like access tokens and environment variables.
It can be combined with force mode to scan for the existence of each hook. This is recommended during MR validation.
Force
Run with the --force
argument to execute the rotation API regardless of the access token's expiry time. This acts as an "emergency button" to ensure all tokens are renewed.
Strict
Run with the --strict
argument. Any error encountered during execution will be raised immediately, stopping the process.
Configuration
Consist of YAML formatted content, see the sample one in sample-config.yml, these are the available properties
Param |
Description |
Defaults |
Required |
.host |
URL of Gitlab instance |
https://gitlab.com/ |
yes |
.token |
Personal access token for GitLab API usage (api scope for all execution, read_api for dry run mode) |
${GL_RENEWER_TOKEN} |
yes |
.default_hook_retry |
Default retry count for hook execution; can be overridden in individual hook configurations |
0 |
yes |
.default_renew_before |
Default duration to renew an access token before expiry; can be overridden in specific access token configs |
14d |
yes |
.default_expiry_after_rotate |
Default duration for token expiration after rotation |
3M |
yes |
.manage_tokens[] |
List of managed access token |
|
yes |
.manage_tokens[].type |
Type of access token (repository , group , or personal ) |
|
yes |
.manage_tokens[].path |
Repository or group location |
|
Required for repository /group |
.manage_tokens[].include |
Include external manage_token configuration, the path is relative to main config file |
|
no |
.manage_tokens[].access_tokens[] |
List of managed access tokens |
|
yes |
.manage_tokens[].access_tokens[].name |
Name of access token |
|
yes |
.manage_tokens[].access_tokens[].renew_before |
Specific renewal period, overriding .default_renew_before |
|
no |
.manage_tokens[].access_tokens[].expiry_after_rotate |
Specific expiration period, overriding .default_expiry_after_rotate |
|
no |
.manage_tokens[].access_tokens[].hooks[] |
List of actions for each hook |
|
no |
.manage_tokens[].access_tokens[].hooks[].type |
Hook type (update_var , exec_cmd , use_token ) |
|
yes |
.manage_tokens[].access_tokens[].hooks[].retry |
Hook retry count, overriding .default_hook_retry |
|
no |
.manage_tokens[].access_tokens[].hooks[].args |
Arguments for each hook type (see details below) |
|
*some hook type is not required |
Notes:
.host
and .token
values can use environment variables in ${THIS_IS_VAR}
format.
- Accepted duration suffixes:
d
(day), M
(month), Y
(year).
- Required arguments for hook types:
update_var
: .type
(repository or group), .path
(location), and name
(variable name).
exec_cmd
: .path
(location of executable) with GL_NEW_TOKEN
as injected environment variable for the new token, you can pass another env variables using .env
.
use_token
: not requiring any arguments, it will uses the new token in the current API call; can only be set once as the first hook.
Development
To avoid "polluting" your local environment and to use a consistent development setup, use devcontainer, which is included in this repository and supports VS Code.
Misc
Utilizing Service Account
For GitLab Premium or higher, it's recommended to use a Service Account's access token instead of one belonging to an active user. Consider leaving its expiration unset and using a self-update approach, as shown in the examples folder.
Separating Between Access Token For Execution
For more information, refer to this example.