Class: Ci::JobToken::Jwt
- Inherits:
-
Object
- Object
- Ci::JobToken::Jwt
- Extended by:
- Gitlab::Utils::StrongMemoize
- Includes:
- Gitlab::Utils::StrongMemoize
- Defined in:
- lib/ci/job_token/jwt.rb
Constant Summary collapse
- LEEWAY =
After finishing, jobs need to be able to POST their final state to the
jobsAPI endpoint, for example to update their status or the final trace. A leeway of 5 minutes ensures a job is able to do that after they have timed out. 5.minutes
Class Method Summary collapse
- .build_payload(job) ⇒ Object
- .decode(token) ⇒ Object
- .encode(job) ⇒ Object
- .expire_time(job) ⇒ Object
- .key ⇒ Object
-
.routable_payload(job) ⇒ Object
Creating routing information for routable tokens handbook.gitlab.com/handbook/engineering/architecture/design-documents/cells/routable_tokens/.
- .subject_type ⇒ Object
- .token_prefix ⇒ Object
Instance Method Summary collapse
- #cell_id ⇒ Object
- #group_id ⇒ Object
-
#initialize(jwt) ⇒ Jwt
constructor
A new instance of Jwt.
- #job ⇒ Object
- #organization_id ⇒ Object
- #project_id ⇒ Object
- #scoped_user ⇒ Object
- #user_id ⇒ Object
Constructor Details
#initialize(jwt) ⇒ Jwt
Returns a new instance of Jwt.
93 94 95 96 97 |
# File 'lib/ci/job_token/jwt.rb', line 93 def initialize(jwt) raise ArgumentError, 'argument is not Authn::Tokens::Jwt' unless jwt.is_a?(::Authn::Tokens::Jwt) @jwt = jwt end |
Class Method Details
.build_payload(job) ⇒ Object
53 54 55 56 |
# File 'lib/ci/job_token/jwt.rb', line 53 def build_payload(job) base_payload = { scoped_user_id: job.scoped_user&.id }.compact_blank base_payload.merge(routable_payload(job)) end |
.decode(token) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/ci/job_token/jwt.rb', line 40 def decode(token) return unless key actual_token_prefix = token.starts_with?(::Ci::Build::TOKEN_PREFIX) ? ::Ci::Build::TOKEN_PREFIX : token_prefix jwt = ::Authn::Tokens::Jwt.rsa_decode( token: token, signing_public_key: key.public_key, subject_type: subject_type, token_prefix: actual_token_prefix) new(jwt) if jwt end |
.encode(job) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ci/job_token/jwt.rb', line 25 def encode(job) return unless job.is_a?(subject_type) return unless job.persisted? return unless key payload = build_payload(job) ::Authn::Tokens::Jwt.rsa_encode( subject: job, signing_key: key, expire_time: expire_time(job), token_prefix: token_prefix, custom_payload: payload) end |
.expire_time(job) ⇒ Object
77 78 79 80 |
# File 'lib/ci/job_token/jwt.rb', line 77 def expire_time(job) ttl = [::JSONWebToken::Token::DEFAULT_EXPIRE_TIME, job.timeout_value.to_i].max Time.current + ttl + LEEWAY end |
.key ⇒ Object
82 83 84 85 86 87 88 89 90 |
# File 'lib/ci/job_token/jwt.rb', line 82 def key signing_key = Gitlab::CurrentSettings.ci_job_token_signing_key raise 'CI job token signing key is not set' unless signing_key OpenSSL::PKey::RSA.new(signing_key.to_s) rescue OpenSSL::PKey::RSAError => error Gitlab::ErrorTracking.track_exception(error) nil end |
.routable_payload(job) ⇒ Object
Creating routing information for routable tokens handbook.gitlab.com/handbook/engineering/architecture/design-documents/cells/routable_tokens/
59 60 61 62 63 64 65 66 67 |
# File 'lib/ci/job_token/jwt.rb', line 59 def routable_payload(job) { c: Gitlab.config.cell.id, o: job.project.organization_id, u: job.user_id, p: job.project_id, g: job.project.group&.id }.compact_blank.transform_values { |id| id.to_s(36) } end |
.subject_type ⇒ Object
73 74 75 |
# File 'lib/ci/job_token/jwt.rb', line 73 def subject_type ::Ci::Build end |
.token_prefix ⇒ Object
69 70 71 |
# File 'lib/ci/job_token/jwt.rb', line 69 def token_prefix ::Authn::TokenField::PrefixHelper.prepend_instance_prefix(::Ci::Build::TOKEN_PREFIX) end |
Instance Method Details
#cell_id ⇒ Object
109 110 111 |
# File 'lib/ci/job_token/jwt.rb', line 109 def cell_id decode(@jwt.payload['c']) end |
#group_id ⇒ Object
125 126 127 |
# File 'lib/ci/job_token/jwt.rb', line 125 def group_id decode(@jwt.payload['g']) end |
#job ⇒ Object
99 100 101 |
# File 'lib/ci/job_token/jwt.rb', line 99 def job @jwt.subject end |
#organization_id ⇒ Object
113 114 115 |
# File 'lib/ci/job_token/jwt.rb', line 113 def organization_id decode(@jwt.payload['o']) end |
#project_id ⇒ Object
117 118 119 |
# File 'lib/ci/job_token/jwt.rb', line 117 def project_id decode(@jwt.payload['p']) end |
#scoped_user ⇒ Object
103 104 105 106 |
# File 'lib/ci/job_token/jwt.rb', line 103 def scoped_user scoped_user_id = @jwt.payload['scoped_user_id'] User.find_by_id(scoped_user_id) if scoped_user_id end |
#user_id ⇒ Object
121 122 123 |
# File 'lib/ci/job_token/jwt.rb', line 121 def user_id decode(@jwt.payload['u']) end |