-
-
Notifications
You must be signed in to change notification settings - Fork 992
Expand file tree
/
Copy pathtrusted_publisher_controller.rb
More file actions
71 lines (59 loc) · 1.98 KB
/
trusted_publisher_controller.rb
File metadata and controls
71 lines (59 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class Api::V1::OIDC::TrustedPublisherController < Api::BaseController
include ApiKeyable
before_action :decode_jwt
before_action :find_provider
before_action :verify_signature
before_action :find_trusted_publisher
before_action :validate_claims
class UnsupportedIssuer < StandardError; end
class UnverifiedJWT < StandardError; end
rescue_from(
UnsupportedIssuer, UnverifiedJWT,
JSON::JWT::VerificationFailed, JSON::JWK::Set::KidNotFound,
OIDC::AccessPolicy::AccessError,
with: :render_not_found
)
def exchange_token
key = generate_unique_rubygems_key
iat = Time.at(@jwt[:iat].to_i, in: "UTC")
api_key = @trusted_publisher.api_keys.create!(
hashed_key: hashed_key(key),
name: "#{@trusted_publisher.name} #{iat.iso8601}",
push_rubygem: true,
expires_at: 15.minutes.from_now
)
render json: {
rubygems_api_key: key,
name: api_key.name,
scopes: api_key.enabled_scopes,
gem: api_key.rubygem,
expires_at: api_key.expires_at
}.compact, status: :created
end
private
def decode_jwt
@jwt = JSON::JWT.decode_compact_serialized(params.require(:jwt), :skip_verification)
rescue JSON::JWT::InvalidFormat, JSON::ParserError, ArgumentError
# invalid base64 raises ArgumentError
render_bad_request
end
def find_provider
@provider = OIDC::Provider.find_by!(issuer: @jwt[:iss])
end
def verify_signature
raise UnverifiedJWT, "Invalid time" unless (@jwt["nbf"]..@jwt["exp"]).cover?(Time.now.to_i)
@jwt.verify!(@provider.jwks)
end
def find_trusted_publisher
unless (trusted_publisher_class = @provider.trusted_publisher_class)
raise UnsupportedIssuer, "Unsuported issuer for trusted publishing"
end
@trusted_publisher = trusted_publisher_class.for_claims(@jwt)
end
def validate_claims
@trusted_publisher.to_access_policy(@jwt).verify_access!(@jwt)
end
def render_bad_request
render json: { error: "Bad Request" }, status: :bad_request
end
end