{"id":17947121,"url":"https://github.com/iomarmochtar/gitlab-token-updater","last_synced_at":"2025-04-30T15:27:39.192Z","repository":{"id":259581774,"uuid":"877203723","full_name":"iomarmochtar/gitlab-token-updater","owner":"iomarmochtar","description":"Manage your Gitlab Access Token Lifetime with ease and enhancing security","archived":false,"fork":false,"pushed_at":"2025-03-09T23:23:55.000Z","size":85,"stargazers_count":12,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-30T17:23:39.600Z","etag":null,"topics":["access-token","gitlab","rotation"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iomarmochtar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-23T09:10:00.000Z","updated_at":"2025-03-09T23:23:59.000Z","dependencies_parsed_at":"2024-10-26T18:01:11.226Z","dependency_job_id":"3df45f07-7a52-45b0-bd72-92a4893d6a6c","html_url":"https://github.com/iomarmochtar/gitlab-token-updater","commit_stats":null,"previous_names":["iomarmochtar/gitlab-token-updater"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iomarmochtar%2Fgitlab-token-updater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iomarmochtar%2Fgitlab-token-updater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iomarmochtar%2Fgitlab-token-updater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iomarmochtar%2Fgitlab-token-updater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iomarmochtar","download_url":"https://codeload.github.com/iomarmochtar/gitlab-token-updater/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251731156,"owners_count":21634523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access-token","gitlab","rotation"],"created_at":"2024-10-29T08:00:26.428Z","updated_at":"2025-04-30T15:27:39.180Z","avatar_url":"https://github.com/iomarmochtar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitLab Access Token Updater/Rotation Manager\n\nThis app addresses the following challenges:\n\n- **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](https://about.gitlab.com/blog/2023/10/25/access-token-lifetime-limits/).\n- **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.\n- **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](https://gitlab.com/groups/gitlab-org/-/epics/9965), requiring manual API calls for management.\n- **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.\n- **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.\n\n## Installation\n\n### Docker\n\nAssuming your main configuration file is located in the current directory:\n\n```bash\ndocker run -v `./config.yml:/tmp/config.yml` -it --rm iomarmochtar/gitlab-token-updater:latest -c /tmp/config.yml\n```\n\n### Compiled\n\nGo to the releases page for a compiled version specific to your OS and architecture.\n\n### Source Build\n\nEnsure to have following package installed on your local:\n- Golang binary with the same version as in [go.mod](./go.mod)\n- [goreleaser](https://goreleaser.com/install/), alternatively, use script [install_goreleaser.sh](./scripts/install_goreleaser.sh) to automate it\n- [GNU Make](https://www.gnu.org/software/make/)\n\nRun following commands:\n\n```bash\ngit clone https://github.com/iomarmochtar/gitlab-token-updater.git\ncd gitlab-token-updater\nmake dist-dev\n```\n\nthe compiled binary is located under folder `dist`\n\n\n## How To Use\n\n### Preparations\n\n#### 1. Personal Access Token\n\nAs Group/Project Access Tokens cannot be used to [create other access token](https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html) related to the access token rotation API ([example](https://docs.gitlab.com/ee/api/project_access_tokens.html#rotate-a-project-access-token)), use a Personal Access Token for access token rotation.\n\nCreate a Personal Access Token with the api scope. You may also create another with the read_api scope for MR dry run purposes.\n\n#### 2. Config File\n\nTo run the application, specify the configuration file with the `-c` or `--config` argument. Other modes are available.\n\n### Execution\n\nFor the normal execution, just poin the configuration file with argument `-c` or `--config`, some of other modes are available\n\n```bash\ngitlab-token-updater -c [PATH_TO_CONFIG_FILE]\n```\n\n#### Mode\n\nYou can enable each mode by adding the respective argument, and they can be used in combination.\n\nIf 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](#strict).\n\n##### Dry Run\n\nRun with the `--dry-run` argument. This will execute read-only APIs and verify the existence of specified objects like access tokens and environment variables.\n\nIt can be combined with [force mode](#force) to scan for the existence of each hook. This is recommended during MR validation.\n\n##### Force\n\nRun 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.\n\n##### Strict\n\nRun with the `--strict` argument. Any error encountered during execution will be raised immediately, stopping the process.\n\n## Configuration\n\nConsist of YAML formatted content, see the sample one in [sample-config.yml](./examples/sample-config.yml), these are the available properties\n\n| Param                                                  | Description                                                                                                 | Defaults              |             Required              |\n| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | --------------------- | :-------------------------------: |\n| `.host`                                                | URL of Gitlab instance                                                                                      | `https://gitlab.com/` |               `yes`               |\n| `.token`                                               | Personal access token for GitLab API usage (api scope for all execution, read_api for dry run mode)         | `${GL_RENEWER_TOKEN}` |               `yes`               |\n| `.default_hook_retry`                                  | Default retry count for hook execution; can be overridden in individual hook configurations                 | `0`                   |               `yes`               |\n| `.default_renew_before`                                | Default duration to renew an access token before expiry; can be overridden in specific access token configs | `14d`                 |               `yes`               |\n| `.default_expiry_after_rotate`                         | Default duration for token expiration after rotation                                                        | `3M`                  |               `yes`               |\n| `.manage_tokens[]`                                     | List of managed access token                                                                                |                       |               `yes`               |\n| `.manage_tokens[].type`                                | Type of access token (`repository`, `group`, or `personal`)                                                 |                       |               `yes`               |\n| `.manage_tokens[].path`                                | Repository or group location                                                                                |                       | Required for `repository`/`group` |\n| `.manage_tokens[].include`                             | Include external `manage_token` configuration, the path is relative to main config file                     |                       |               `no`                |\n| `.manage_tokens[].access_tokens[]`                     | List of managed access tokens                                                                               |                       |               `yes`               |\n| `.manage_tokens[].access_tokens[].name`                | Name of access token                                                                                        |                       |               `yes`               |\n| `.manage_tokens[].access_tokens[].renew_before`        | Specific renewal period, overriding `.default_renew_before`                                                 |                       |               `no`                |\n| `.manage_tokens[].access_tokens[].expiry_after_rotate` | Specific expiration period, overriding `.default_expiry_after_rotate`                                       |                       |               `no`                |\n| `.manage_tokens[].access_tokens[].hooks[]`             | List of actions for each hook                                                                               |                       |               `no`                |\n| `.manage_tokens[].access_tokens[].hooks[].type`        | Hook type (`update_var`, `exec_cmd`, `use_token`)                                                           |                       |               `yes`               |\n| `.manage_tokens[].access_tokens[].hooks[].retry`       | Hook retry count, overriding `.default_hook_retry`                                                          |                       |               `no`                |\n| `.manage_tokens[].access_tokens[].hooks[].args`        | Arguments for each hook type (see details below)                                                            |                       |  *some hook type is not required  |\n\n**Notes:**\n\n- the config value can be injected by env variable by using format `${THIS_IS_VAR}` and it's only available in following locations:\n  - `.host`\n  - `.token`\n  - `.manage_tokens[].access_tokens[].hooks[].args` for hook type `update_var`\n  - `.manage_tokens[].access_tokens[].hooks[].args.env` for hook type `exec_cmd`\n- Known duration suffixes: `d` (day), `M` (month), `Y` (year).\n- hook types with it's available arguments:\n  - `update_var`:\n    - `.name` (required): CICD variable name\n    - `.type` (required): `repository` or `group`\n    - `.path` (required): location of repository or group\n    - `.gitlab`: set this if CICD variable is located in another Gitlab instance\n    - `.gitlab_token`: the token that will be used to another Gitlab instance as in `.gitlab`\n    - misc:\n      - if `.type` and `.path` are not defined, then it will use the same as in it's parent (manage token config)\n      - `.gitlab-token` is required when `.gitlab` configured, and suggested set in env variable\n  - `exec_cmd`:\n    - `.path` (required): location of executable\n    - `.env`: set the injected environment variable that will be read by the executeable\n    - misc:\n      - the new generated token that read in the executeable is through env variable by name `GL_NEW_TOKEN`\n  - `use_token`: not requiring any arguments, it will uses the new token in the current API call; can only be set once in the first hook sequence.\n\n## Development\n\nTo avoid \"polluting\" your local environment and to use a consistent development setup, use [devcontainer](https://containers.dev/), which is included in this repository and a built in feature in Visual Studio Code.\n\n## Misc\n\n### Utilizing Service Account\n\nFor 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](./examples/).\n\n### Separating Between Access Token For Execution\n\nFor more information, refer to [this example](./examples/README.md).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiomarmochtar%2Fgitlab-token-updater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiomarmochtar%2Fgitlab-token-updater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiomarmochtar%2Fgitlab-token-updater/lists"}