-
-
Notifications
You must be signed in to change notification settings - Fork 902
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
80 changed files
with
3,067 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
app/avo/resources/oidc_pending_trusted_publisher_resource.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
class OIDCPendingTrustedPublisherResource < Avo::BaseResource | ||
self.title = :id | ||
self.includes = [] | ||
self.model_class = ::OIDC::PendingTrustedPublisher | ||
|
||
class ExpiredFilter < ScopeBooleanFilter; end | ||
filter ExpiredFilter, arguments: { default: { expired: false, unexpired: true } } | ||
|
||
field :id, as: :id | ||
# Fields generated from the model | ||
field :rubygem_name, as: :text | ||
field :user, as: :belongs_to | ||
field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher | ||
field :expires_at, as: :date_time | ||
# add fields here | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
app/avo/resources/oidc_rubygem_trusted_publisher_resource.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class OIDCRubygemTrustedPublisherResource < Avo::BaseResource | ||
self.title = :id | ||
self.includes = [:trusted_publisher] | ||
self.model_class = ::OIDC::RubygemTrustedPublisher | ||
|
||
field :id, as: :id | ||
# Fields generated from the model | ||
field :rubygem, as: :belongs_to | ||
field :trusted_publisher, as: :belongs_to, polymorphic_as: :trusted_publisher | ||
# add fields here | ||
end |
19 changes: 19 additions & 0 deletions
19
app/avo/resources/oidc_trusted_publisher_github_action_resource.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class OIDCTrustedPublisherGitHubActionResource < Avo::BaseResource | ||
self.title = :name | ||
self.includes = [] | ||
self.model_class = ::OIDC::TrustedPublisher::GitHubAction | ||
|
||
field :id, as: :id | ||
# Fields generated from the model | ||
field :repository_owner, as: :text | ||
field :repository_name, as: :text | ||
field :repository_owner_id, as: :text | ||
field :workflow_filename, as: :text | ||
field :environment, as: :text | ||
# add fields here | ||
# | ||
field :rubygem_trusted_publishers, as: :has_many | ||
field :pending_trusted_publishers, as: :has_many | ||
field :rubygems, as: :has_many, through: :rubygem_trusted_publishers | ||
field :api_keys, as: :has_many, inverse_of: :owner | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
app/controllers/api/v1/oidc/trusted_publisher_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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 |
4 changes: 4 additions & 0 deletions
4
app/controllers/avo/oidc_pending_trusted_publishers_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# This controller has been generated to enable Rails' resource routes. | ||
# More information on https://docs.avohq.io/2.0/controllers.html | ||
class Avo::OIDCPendingTrustedPublishersController < Avo::ResourcesController | ||
end |
4 changes: 4 additions & 0 deletions
4
app/controllers/avo/oidc_rubygem_trusted_publishers_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# This controller has been generated to enable Rails' resource routes. | ||
# More information on https://docs.avohq.io/2.0/controllers.html | ||
class Avo::OIDCRubygemTrustedPublishersController < Avo::ResourcesController | ||
end |
4 changes: 4 additions & 0 deletions
4
app/controllers/avo/oidc_trusted_publisher_github_actions_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# This controller has been generated to enable Rails' resource routes. | ||
# More information on https://docs.avohq.io/2.0/controllers.html | ||
class Avo::OIDCTrustedPublisherGitHubActionsController < Avo::ResourcesController | ||
end |
21 changes: 21 additions & 0 deletions
21
app/controllers/oidc/concerns/trusted_publisher_creation.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module OIDC::Concerns::TrustedPublisherCreation | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
include SessionVerifiable | ||
verify_session_before | ||
|
||
before_action :set_trusted_publisher_type, only: %i[create] | ||
before_action :create_params, only: %i[create] | ||
before_action :set_page, only: :index | ||
end | ||
|
||
def set_trusted_publisher_type | ||
trusted_publisher_type = params.permit(create_params_key => :trusted_publisher_type).require(create_params_key).require(:trusted_publisher_type) | ||
|
||
@trusted_publisher_type = OIDC::TrustedPublisher.all.find { |type| type.polymorphic_name == trusted_publisher_type } | ||
|
||
return if @trusted_publisher_type | ||
redirect_back fallback_location: root_path, flash: { error: t("oidc.trusted_publisher.unsupported_type") } | ||
end | ||
end |
65 changes: 65 additions & 0 deletions
65
app/controllers/oidc/pending_trusted_publishers_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
class OIDC::PendingTrustedPublishersController < ApplicationController | ||
include OIDC::Concerns::TrustedPublisherCreation | ||
|
||
before_action :find_pending_trusted_publisher, only: %i[destroy] | ||
|
||
def index | ||
trusted_publishers = current_user | ||
.oidc_pending_trusted_publishers.unexpired.includes(:trusted_publisher) | ||
.order(:rubygem_name, :created_at).page(@page).strict_loading | ||
render OIDC::PendingTrustedPublishers::IndexView.new( | ||
trusted_publishers: | ||
) | ||
end | ||
|
||
def new | ||
pending_trusted_publisher = current_user.oidc_pending_trusted_publishers.new(trusted_publisher: OIDC::TrustedPublisher::GitHubAction.new) | ||
render OIDC::PendingTrustedPublishers::NewView.new( | ||
pending_trusted_publisher: | ||
) | ||
end | ||
|
||
def create | ||
trusted_publisher = current_user.oidc_pending_trusted_publishers.new( | ||
create_params.merge( | ||
expires_at: 12.hours.from_now | ||
) | ||
) | ||
|
||
if trusted_publisher.save | ||
redirect_to profile_oidc_pending_trusted_publishers_path, flash: { notice: t(".success") } | ||
else | ||
flash.now[:error] = trusted_publisher.errors.full_messages.to_sentence | ||
render OIDC::PendingTrustedPublishers::NewView.new( | ||
pending_trusted_publisher: trusted_publisher | ||
), status: :unprocessable_entity | ||
end | ||
end | ||
|
||
def destroy | ||
if @pending_trusted_publisher.destroy | ||
redirect_to profile_oidc_pending_trusted_publishers_path, flash: { notice: t(".success") } | ||
else | ||
redirect_back fallback_location: profile_oidc_pending_trusted_publishers_path, | ||
flash: { error: @pending_trusted_publisher.errors.full_messages.to_sentence } | ||
end | ||
end | ||
|
||
private | ||
|
||
def create_params | ||
params.permit( | ||
create_params_key => [ | ||
:rubygem_name, | ||
:trusted_publisher_type, | ||
{ trusted_publisher_attributes: @trusted_publisher_type.permitted_attributes } | ||
] | ||
).require(create_params_key) | ||
end | ||
|
||
def create_params_key = :oidc_pending_trusted_publisher | ||
|
||
def find_pending_trusted_publisher | ||
@pending_trusted_publisher = current_user.oidc_pending_trusted_publishers.find(params.require(:id)) | ||
end | ||
end |
80 changes: 80 additions & 0 deletions
80
app/controllers/oidc/rubygem_trusted_publishers_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
class OIDC::RubygemTrustedPublishersController < ApplicationController | ||
include OIDC::Concerns::TrustedPublisherCreation | ||
|
||
before_action :find_rubygem | ||
before_action :render_forbidden, unless: :owner? | ||
before_action :find_rubygem_trusted_publisher, except: %i[index new create] | ||
|
||
def index | ||
render OIDC::RubygemTrustedPublishers::IndexView.new( | ||
rubygem: @rubygem, | ||
trusted_publishers: @rubygem.oidc_rubygem_trusted_publishers.includes(:trusted_publisher).page(@page).strict_loading | ||
) | ||
end | ||
|
||
def new | ||
render OIDC::RubygemTrustedPublishers::NewView.new( | ||
rubygem_trusted_publisher: @rubygem.oidc_rubygem_trusted_publishers.new(trusted_publisher: gh_actions_trusted_publisher) | ||
) | ||
end | ||
|
||
def create | ||
trusted_publisher = @rubygem.oidc_rubygem_trusted_publishers.new( | ||
create_params | ||
) | ||
|
||
if trusted_publisher.save | ||
redirect_to rubygem_trusted_publishers_path(@rubygem.slug), flash: { notice: t(".success") } | ||
else | ||
flash.now[:error] = trusted_publisher.errors.full_messages.to_sentence | ||
render OIDC::RubygemTrustedPublishers::NewView.new( | ||
rubygem_trusted_publisher: trusted_publisher | ||
), status: :unprocessable_entity | ||
end | ||
end | ||
|
||
def destroy | ||
if @rubygem_trusted_publisher.destroy | ||
redirect_to rubygem_trusted_publishers_path(@rubygem.slug), flash: { notice: t(".success") } | ||
else | ||
redirect_back fallback_location: rubygem_trusted_publishers_path(@rubygem.slug), | ||
flash: { error: @rubygem_trusted_publisher.errors.full_messages.to_sentence } | ||
end | ||
end | ||
|
||
private | ||
|
||
def create_params | ||
params.permit( | ||
create_params_key => [ | ||
:trusted_publisher_type, | ||
{ trusted_publisher_attributes: @trusted_publisher_type.permitted_attributes } | ||
] | ||
).require(create_params_key) | ||
end | ||
|
||
def create_params_key = :oidc_rubygem_trusted_publisher | ||
|
||
def find_rubygem_trusted_publisher | ||
@rubygem_trusted_publisher = @rubygem.oidc_rubygem_trusted_publishers.find(params.require(:id)) | ||
end | ||
|
||
def gh_actions_trusted_publisher | ||
github_params = helpers.github_params(@rubygem) | ||
|
||
publisher = OIDC::TrustedPublisher::GitHubAction.new | ||
if github_params | ||
publisher.repository_owner = github_params[:user] | ||
publisher.repository_name = github_params[:repo] | ||
publisher.workflow_filename = workflow_filename(publisher.repository) | ||
end | ||
publisher | ||
end | ||
|
||
def workflow_filename(repo) | ||
paths = Octokit.contents(repo, path: ".github/workflows").lazy.select { _1.type == "file" }.map(&:name).grep(/\.ya?ml\z/) | ||
paths.max_by { |path| [path.include?("release"), path.include?("push")].map! { (_1 && 1) || 0 } } | ||
rescue Octokit::NotFound | ||
nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.