Closed balasankarc closed 7 months ago
Maybe something like the following?
diff --git a/lib/gitlab/configuration.rb b/lib/gitlab/configuration.rb
index 8c37354..fa5fcc7 100644
--- a/lib/gitlab/configuration.rb
+++ b/lib/gitlab/configuration.rb
@@ -5,7 +5,7 @@ module Gitlab
# Defines constants and methods related to configuration.
module Configuration
# An array of valid keys in the options hash when configuring a Gitlab::API.
- VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httparty].freeze
+ VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httparty pat_prefix].freeze
# The user agent that will be sent to the API endpoint if none is set.
DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}"
@@ -37,6 +37,7 @@ module Gitlab
def reset
self.endpoint = ENV['GITLAB_API_ENDPOINT'] || ENV['CI_API_V4_URL']
self.private_token = ENV['GITLAB_API_PRIVATE_TOKEN'] || ENV['GITLAB_API_AUTH_TOKEN']
+ self.pat_prefix = 'glpat-'
self.httparty = get_httparty_config(ENV['GITLAB_API_HTTPARTY_OPTIONS'])
self.sudo = nil
self.user_agent = DEFAULT_USER_AGENT
diff --git a/lib/gitlab/request.rb b/lib/gitlab/request.rb
index 218b81b..307f5ee 100644
--- a/lib/gitlab/request.rb
+++ b/lib/gitlab/request.rb
@@ -12,7 +12,7 @@ module Gitlab
headers 'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'
parser(proc { |body, _| parse(body) })
- attr_accessor :private_token, :endpoint
+ attr_accessor :private_token, :endpoint, :pat_prefix
# Converts the response body to an ObjectifiedHash.
def self.parse(body)
@@ -93,10 +93,21 @@ module Gitlab
def authorization_header
raise Error::MissingCredentials, 'Please provide a private_token or auth_token for user' unless private_token
- if private_token.size < 21
+ pat_prefix ||= 'glpat-'
+
+ # The Personal Access Token prefix can be at most 20 characters, and the
+ # generated part is of length 20 characters. Personal Access Tokens, thus
+ # can have a maximum size of 40 characters. GitLab uses
+ # `Doorkeeper::OAuth::Helpers::UniqueToken.generate` for generating
+ # OAuth2 tokens, and specified `hex` as token generator method. Thus, the
+ # OAuth2 tokens are of length more than 64. If the token length is below
+ # that, it is probably a Personal Access Token or CI_JOB_TOKEN.
+ if private_token.size >= 64
+ { 'Authorization' => "Bearer #{private_token}" }
+ elsif private_token.start_with?(pat_prefix)
{ 'PRIVATE-TOKEN' => private_token }
else
- { 'Authorization' => "Bearer #{private_token}" }
+ { 'JOB-TOKEN' => private_token }
end
end
I tested the above diff in https://gitlab.com/balasankarc/test-ci-job-token-gitlab-gem/-/jobs/4372664465 (you can check https://gitlab.com/balasankarc/test-ci-job-token-gitlab-gem/-/blob/main/code.rb to see what it does)
@balasankarc 👋 do you think we can have the token be a bit smarter without requiring pat_prefix
? My understanding is that the prefix is not relevant... we can test if ENV['CI_JOB_TOKEN']
is present and use the 'JOB-TOKEN' instead, wdyt?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
not stale
@brodock Users might want to explicitly use a normal PAT even in CI, because Job token can't access all endpoints. Which is why I went with making it an explicit decision than an automatic detection.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
When using the job token, the header needs to be
JOB-TOKEN
instead ofPRIVATE-TOKEN
.Starting with GitLab 14.5,
glpat-
is used as a default prefix for personal access tokens (though this is configurable). So maybe we can acceptpat_prefix
as an argument, and then detect if the specified token starts with it or not, and then set the headers accordingly?