2020-04-22 19:07:51 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module Ci
|
|
|
|
class Jwt
|
|
|
|
NOT_BEFORE_TIME = 5
|
|
|
|
DEFAULT_EXPIRE_TIME = 60 * 5
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
NoSigningKeyError = Class.new(StandardError)
|
|
|
|
|
2020-04-22 19:07:51 +05:30
|
|
|
def self.for_build(build)
|
|
|
|
self.new(build, ttl: build.metadata_timeout).encoded
|
|
|
|
end
|
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
def initialize(build, ttl:)
|
2020-04-22 19:07:51 +05:30
|
|
|
@build = build
|
|
|
|
@ttl = ttl
|
|
|
|
end
|
|
|
|
|
|
|
|
def payload
|
|
|
|
custom_claims.merge(reserved_claims)
|
|
|
|
end
|
|
|
|
|
|
|
|
def encoded
|
|
|
|
headers = { kid: kid, typ: 'JWT' }
|
|
|
|
|
|
|
|
JWT.encode(payload, key, 'RS256', headers)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
attr_reader :build, :ttl
|
2020-04-22 19:07:51 +05:30
|
|
|
|
2023-07-09 08:55:56 +05:30
|
|
|
delegate :project, :user, :pipeline, :runner, to: :build
|
|
|
|
delegate :source_ref, :source_ref_path, to: :pipeline
|
|
|
|
delegate :public_key, to: :key
|
|
|
|
delegate :namespace, to: :project
|
|
|
|
|
2020-04-22 19:07:51 +05:30
|
|
|
def reserved_claims
|
|
|
|
now = Time.now.to_i
|
|
|
|
|
|
|
|
{
|
|
|
|
jti: SecureRandom.uuid,
|
|
|
|
iss: Settings.gitlab.host,
|
|
|
|
iat: now,
|
|
|
|
nbf: now - NOT_BEFORE_TIME,
|
|
|
|
exp: now + (ttl || DEFAULT_EXPIRE_TIME),
|
|
|
|
sub: "job_#{build.id}"
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def custom_claims
|
2021-03-11 19:13:27 +05:30
|
|
|
fields = {
|
2020-04-22 19:07:51 +05:30
|
|
|
namespace_id: namespace.id.to_s,
|
|
|
|
namespace_path: namespace.full_path,
|
|
|
|
project_id: project.id.to_s,
|
|
|
|
project_path: project.full_path,
|
|
|
|
user_id: user&.id.to_s,
|
|
|
|
user_login: user&.username,
|
|
|
|
user_email: user&.email,
|
2023-07-09 08:55:56 +05:30
|
|
|
pipeline_id: pipeline.id.to_s,
|
|
|
|
pipeline_source: pipeline.source.to_s,
|
2020-04-22 19:07:51 +05:30
|
|
|
job_id: build.id.to_s,
|
|
|
|
ref: source_ref,
|
|
|
|
ref_type: ref_type,
|
2023-07-09 08:55:56 +05:30
|
|
|
ref_path: source_ref_path,
|
2020-04-22 19:07:51 +05:30
|
|
|
ref_protected: build.protected.to_s
|
|
|
|
}
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
if environment.present?
|
2021-03-11 19:13:27 +05:30
|
|
|
fields.merge!(
|
|
|
|
environment: environment.name,
|
2022-08-13 15:12:31 +05:30
|
|
|
environment_protected: environment_protected?.to_s,
|
2022-08-27 11:52:29 +05:30
|
|
|
deployment_tier: build.environment_tier
|
2021-03-11 19:13:27 +05:30
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
fields
|
2020-04-22 19:07:51 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def key
|
2021-01-29 00:20:46 +05:30
|
|
|
@key ||= begin
|
2022-07-23 23:45:48 +05:30
|
|
|
key_data = Gitlab::CurrentSettings.ci_jwt_signing_key
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
raise NoSigningKeyError unless key_data
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
OpenSSL::PKey::RSA.new(key_data)
|
|
|
|
end
|
2020-04-22 19:07:51 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def kid
|
|
|
|
public_key.to_jwk[:kid]
|
|
|
|
end
|
|
|
|
|
|
|
|
def ref_type
|
|
|
|
::Ci::BuildRunnerPresenter.new(build).ref_type
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
def environment
|
|
|
|
build.persisted_environment
|
|
|
|
end
|
|
|
|
|
|
|
|
def environment_protected?
|
|
|
|
false # Overridden in EE
|
|
|
|
end
|
2020-04-22 19:07:51 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
Gitlab::Ci::Jwt.prepend_mod_with('Gitlab::Ci::Jwt')
|