From 85928e724ceffce24033ef08dcd82f6b628f1f83 Mon Sep 17 00:00:00 2001 From: Girija Soni Date: Wed, 11 Dec 2024 14:45:16 +0530 Subject: [PATCH] Fixes #37936 - Invalidate jwt for any user or users(API) --- .../api/v2/registration_tokens_controller.rb | 58 +++++++++++++++++++ config/initializers/f_foreman_permissions.rb | 3 +- config/routes/api/v2.rb | 7 +++ .../v2/registration_tokens_controller_test.rb | 38 ++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 app/controllers/api/v2/registration_tokens_controller.rb create mode 100644 test/controllers/api/v2/registration_tokens_controller_test.rb diff --git a/app/controllers/api/v2/registration_tokens_controller.rb b/app/controllers/api/v2/registration_tokens_controller.rb new file mode 100644 index 00000000000..244c2b5c5bd --- /dev/null +++ b/app/controllers/api/v2/registration_tokens_controller.rb @@ -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 diff --git a/config/initializers/f_foreman_permissions.rb b/config/initializers/f_foreman_permissions.rb index 15e469c150c..5cf7a234963 100644 --- a/config/initializers/f_foreman_permissions.rb +++ b/config/initializers/f_foreman_permissions.rb @@ -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] diff --git a/config/routes/api/v2.rb b/config/routes/api/v2.rb index 3eca161f873..e422b4283d5 100644 --- a/config/routes/api/v2.rb +++ b/config/routes/api/v2.rb @@ -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 diff --git a/test/controllers/api/v2/registration_tokens_controller_test.rb b/test/controllers/api/v2/registration_tokens_controller_test.rb new file mode 100644 index 00000000000..2cb2d95b67a --- /dev/null +++ b/test/controllers/api/v2/registration_tokens_controller_test.rb @@ -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 => "foo@bar.com", :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