Skip to content

Commit

Permalink
Fixes #37936 - Invalidate jwt for any user or users(API)
Browse files Browse the repository at this point in the history
  • Loading branch information
girijaasoni committed Dec 11, 2024
1 parent 4508c79 commit 85928e7
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 1 deletion.
58 changes: 58 additions & 0 deletions app/controllers/api/v2/registration_tokens_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module Api
module V2
class RegistrationTokensController < V2::BaseController
include Foreman::Controller::UsersMixin

include Foreman::Controller::Parameters::User
before_action :authenticate, :only => [:invalidate_tokens]

def resource_class
User
end

def find_resource(permission = :view_users)
editing_self? ? User.find(User.current.id) : User.authorized(permission).except_hidden.find(params[:id])
end

def action_permission
case params[:action]
when 'invalidate_tokens', 'destroy'
'edit'
else
super
end
end

api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all registration Tokens for a specific user.")
description <<-DOC
The user you specify will no longer be able to register hosts by using their JWTs.
DOC
param :id, String, :desc => N_("ID of the user"), :required => true

def destroy
@user = find_resource(:edit_users)
unless @user
raise ::Foreman::Exception.new(N_("No record found for %s"), params[:id])
end
@user.jwt_secret&.destroy
process_success _('Successfully invalidated JWTs for %s.' % @user.login)
end

api :DELETE, "/registration_tokens", N_("Invalidate all JSON Web Tokens (JWTs) for multiple users.")
param :search, String, :required => true
description <<-DOC
The users you specify will no longer be able to register hosts by using their JWTs.
DOC

def invalidate_tokens
raise ::Foreman::Exception.new(N_("Please provide search parameters")) if params[:search].blank?
@users = resource_scope_for_index(:permission => :edit_users).except_hidden.uniq
if @users.blank?
raise ::Foreman::Exception.new(N_("No record found for %s"), params[:search])
end
JwtSecret.where(user_id: @users).destroy_all
process_success _('Successfully invalidated JWTs for %s.' % @users.pluck(:login).to_sentence)
end
end
end
end
3 changes: 2 additions & 1 deletion config/initializers/f_foreman_permissions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,8 @@
:"api/v2/users" => [:create]
map.permission :edit_users,
:users => [:edit, :update, :invalidate_jwt],
:"api/v2/users" => [:update]
:"api/v2/users" => [:update],
:"api/v2/registration_tokens" => [:invalidate_tokens, :destroy]
map.permission :destroy_users,
:users => [:destroy],
:"api/v2/users" => [:destroy]
Expand Down
7 changes: 7 additions & 0 deletions config/routes/api/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@
resources :mail_notifications, :only => [:create, :destroy, :update]
get 'mail_notifications', :to => 'mail_notifications#user_mail_notifications', :on => :member
get 'extlogin', :to => 'users#extlogin', :on => :collection
delete 'registration_tokens', :to => 'registration_tokens#destroy', :on => :member
end
end

resources :registration_tokens, :only => [:invalidate_tokens] do
collection do
delete '/', :action => :invalidate_tokens
end
end

Expand Down
38 changes: 38 additions & 0 deletions test/controllers/api/v2/registration_tokens_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'test_helper'

class Api::V2::RegistrationTokensControllerTest < ActionController::TestCase
test 'user shall invalidate tokens for self' do
user = User.create :login => "foo", :mail => "[email protected]", :auth_source => auth_sources(:one)
FactoryBot.build(:jwt_secret, token: 'test_jwt_secret', user: user)
delete :destroy, params: { :id => user.id.to_s}
user.reload
assert_response :success
end

test 'user with edit permission should be able to invalidate jwt for another user' do
setup_user 'edit', 'users'
user = users(:scoped)
FactoryBot.build(:jwt_secret, token: 'test_jwt_secret', user: user)
delete :invalidate_tokens, params: { :search => "id ^ (#{user.id})"}
user.reload
assert_response :success
end

test 'user without edit permission should not be able to invalidate jwt for another user' do
User.current = users(:one)
user = users(:scoped)
FactoryBot.build(:jwt_secret, token: 'test_jwt_secret', user: user)
delete :invalidate_tokens, params: { :search => "id ^ (#{user.id})"}
user.reload
assert_response :forbidden
end

test 'invalidating jwt should fail without search params' do
setup_user 'edit', 'users'
user = users(:scoped)
FactoryBot.build(:jwt_secret, token: 'test_jwt_secret', user: user)
delete :invalidate_tokens
user.reload
assert_response :error
end
end

0 comments on commit 85928e7

Please sign in to comment.