-
Notifications
You must be signed in to change notification settings - Fork 676
Description
Description of the problem, including code/CLI snippet
Generic 401/403s make CI_JOB_TOKEN
troubleshooting slow. Users can’t easily tell if a token is a job token, private/OAuth, or just out of scope.
One may verify that their CI_JOB_TOKEN
is valid via any of:
$ wget -O- --header "JOB-TOKEN: $CI_JOB_TOKEN" "${CI_API_V4_URL}/job" || :
Connecting to gitlab.xx_xx_xx.com (xx.xx.xx.xx:443)
writing to stdout
{"id":xxxxxxx,"status":"running","stage":"deploy","name":"xx_xxx","ref":"xxxxxx/xxxxxxx/debug-job-issue","tag":false,"coverage":null,"allow_failure":false,"created_at":"2025-08-25T08:45:12.045Z","started_at":"2025-08-25T08:45:21.130Z","finished_at":null,"erased_at":null,"duration":11.964642337,"queued_duration":8.933698,"user":{"id":xxxx,"username":"x","name":"x","state":"active","locked":false,"avatar_url":"https://secure.gravatar.com/avatar/x?s=80\u0026d=identicon","web_url":"https://gitlab.xx_xx_xx.com/x","created_at":"2022-04-11T07:53:06.941Z"},"commit":{"id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","short_id":"xxxxxxxx","created_at":"2025-08-22T18:21:27.000+03:00","parent_ids":["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"],"title":"debug locally","message":"debug locally\n\nSigned-off-by: x \u003cx@users.noreply.gitlab.com\u003e\n","author_name":"x","author_email":"x@users.noreply.gitlab.com","authored_date":"2025-08-22T16:51:15.000+03:00","committer_name":"x","committer_email":"x@users.noreply.gitlab.com","committed_date":"2025-08-22T18:21:27.000+03:00","web_url":"https://gitlab.xx_xx_xx.com/x-x/x-x/-/commit/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},"pipeline":{"id":xxxxxxx,"iid":xx,"project_id":xxxx,"sha":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","ref":"xxxxxx/xxxxxxx/debug-job-issue","status":"running","source":"web","created_at":"2025-08-22T15:21:52.835Z","updated_at":"2025-08-25T08:45:12.236Z","web_url":"https://gitlab.xx_xx_xx.com/x-x/x-x/-/pipelines/xxxxxxx"},"web_url":"https://gitlab.xx_xx_xx.com/x-x/x-x/-/jobs/xxxxxxx","project":{"ci_job_token_scope_enabled":false},"artifacts":[],"runner":{"id":xxxxxx,"description":"global-small","active":true,"paused":false,"is_shared":true,"runner_type":"instance_type","name":"gitlab-runner","online":true,"status":"online"},"runner_manager":{"id":xxxxx,"system_id":"xxxxxxxxxxxxxx","version":"xx.xx.x","revision":"xxxxxxxx","platform":"linux","architecture":"amd64","created_at":"2025-08-21T00:15:32.832Z","contacted_at":"2025-08-25T08:45:32.806Z","ip_address":"xx.xxx.x.xxx","status":"online"},"artifacts_expire_at":null,"archived":false,"tag_list":["global-small"]}- 100% |********************************| 2796 0:00:00 ETA
written to stdout
$ wget -O- --header "JOB-TOKEN: $CI_JOB_TOKEN" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/environments" || :
Connecting to gitlab.xx_xx_xx.com (xx.xx.xx.xx:443)
writing to stdout
[]- 100% |********************************| 2 0:00:00 ETA
written to stdout
$ wget -O- --header "JOB-TOKEN: $CI_JOB_TOKEN" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/releases" || :
Connecting to gitlab.xx_xx_xx.com (xx.xx.xx.xx:443)
writing to stdout
[]- 100% |********************************| 2 0:00:00 ETA
written to stdout
However, trying to use a CI_JOB_TOKEN
(and failing) can have many causes. In my case, someone "impersonated" CI_JOB_TOKEN
for some kind of token.
I think python-gitlab telling me "are you sure xyz is indeed a CI_JOB_TOKEN
, and in-scope (owning job still needs to be running)?" would've led me to this conclusion faster.
Ofc, Gitlab does not "expose what kind of token X is" - but $CI_JOB_TOKEN /job
is a good indicator for a job_token
.
Additionally, you have:
python-gitlab/docs/api-usage.rst
Lines 49 to 51 in d40d5d2
# make an API request to create the gl.user object. This is not required but may be useful | |
# to validate your token authentication. Note that this will not work with job tokens. | |
gl.auth() |
Validating/Working with a CI_JOB_TOKEN
can be PITN - I think python-gitlab telling me "are you sure xyz is indeed a CI_JOB_TOKEN
?" would've led me to resolution faster.
Note that GET /job
is "immune" to fine-grained (job token) permissions (https://docs.gitlab.com/ci/jobs/fine_grained_permissions/)
Expected Behavior
My suggestion would be
Would you be open in incorporating e.g. gitlab.http_get("/job")
inside gl.auth()
when one is using the job_token=
?
(I couldn't find an gitlab.job()
endpoint, hence the #http_get()
)
Actual Behavior
Specifications
- python-gitlab version:
- Gitlab server version (or gitlab.com):
Additionals
Ofc, Gitlab does not "expose what kind of token X is" - but $CI_JOB_TOKEN /job
is a good indicator for job_token
. To be honest, I would've made a troubleshooting command for myself:
- check
/user
[if token is private], - check
/job
[if token is CI_JOB_TOKEN], - moar logic here
to verify dev's/user's "claims" i.e. using gitlab.Gitlab(url, private_token=private_token)
, gitlab.Gitlab(url, job_token=job_token)