diff --git a/app/controllers/api/v2/registration_commands_controller.rb b/app/controllers/api/v2/registration_commands_controller.rb index 8c8bb6984a9..6163f47d370 100644 --- a/app/controllers/api/v2/registration_commands_controller.rb +++ b/app/controllers/api/v2/registration_commands_controller.rb @@ -5,7 +5,6 @@ class RegistrationCommandsController < V2::BaseController include Foreman::Controller::RegistrationCommands before_action :find_smart_proxy, if: -> { registration_params['smart_proxy_id'] } - api :POST, "/registration_commands", N_("Generate global registration command") param :registration_command, Hash, required: false, action_aware: true do param :organization_id, :number, desc: N_("ID of the Organization to register the host in") @@ -15,7 +14,7 @@ class RegistrationCommandsController < V2::BaseController param :smart_proxy_id, :number, desc: N_("ID of the Smart Proxy. This Proxy must have enabled both the 'Templates' and 'Registration' features") param :setup_insights, :bool, desc: N_("Set 'host_registration_insights' parameter for the host. If it is set to true, insights client will be installed and registered on Red Hat family operating systems") param :setup_remote_execution, :bool, desc: N_("Set 'host_registration_remote_execution' parameter for the host. If it is set to true, SSH keys will be installed on the host") - param :jwt_expiration, :number, desc: N_("Expiration of the authorization token (in hours)") + param :jwt_expiration, :number, desc: N_("Expiration of the authorization token (in hours), 0 means 'unlimited'.") param :insecure, :bool, desc: N_("Enable insecure argument for the initial curl") param :packages, String, desc: N_("Packages to install on the host when registered. Can be set by `host_packages` parameter, example: `pkg1 pkg2`") param :update_packages, :bool, desc: N_("Update all packages on the host") diff --git a/app/controllers/concerns/foreman/controller/registration_commands.rb b/app/controllers/concerns/foreman/controller/registration_commands.rb index 4c2b47fb724..18aef1b98ad 100644 --- a/app/controllers/concerns/foreman/controller/registration_commands.rb +++ b/app/controllers/concerns/foreman/controller/registration_commands.rb @@ -3,6 +3,10 @@ module Foreman::Controller::RegistrationCommands private + MIN_VALUE = 0 + MAX_VALUE = 999999 + DEFAULT_VALUE = 4 + def command args_query = "?#{registration_args.to_query}" "set -o pipefail && curl -sS #{insecure} '#{registration_url(@smart_proxy)}#{args_query if args_query != '?'}' #{command_headers} | bash" @@ -27,17 +31,40 @@ def registration_url(proxy = nil) "#{url}/register" end + def invalid_expiration_error + raise ::Foreman::Exception.new(N_("Invalid value '%s' for jwt_expiration. The value must be between %s and %s. 0 means 'unlimited'."), registration_params['jwt_expiration'], MIN_VALUE, MAX_VALUE) + end + + def jwt_expiration_param + param = registration_params['jwt_expiration'] || DEFAULT_VALUE + @jwt_expiration_param ||= begin + if param == 'unlimited' + 0 + elsif Float(param, exception: false) + param.to_i + else + invalid_expiration_error + end + end + end + + def expiration_unlimited? + jwt_expiration_param == 0 + end + + def expiration_valid? + jwt_expiration_param.between?(MIN_VALUE, MAX_VALUE) + end + def command_headers jwt_args = { scope: [{ controller: :registration, actions: [:global, :host] }], } - - if registration_params['jwt_expiration'].present? - jwt_args[:expiration] = registration_params['jwt_expiration'].to_i.hours.to_i if registration_params['jwt_expiration'] != 'unlimited' + if expiration_valid? + jwt_args[:expiration] = jwt_expiration_param.hours.to_i unless expiration_unlimited? else - jwt_args[:expiration] = 4.hours.to_i + invalid_expiration_error end - "-H 'Authorization: Bearer #{User.current.jwt_token!(**jwt_args)}'" end diff --git a/test/controllers/registration_commands_controller_test.rb b/test/controllers/registration_commands_controller_test.rb index 4d4b52c8a1f..b0bc2b69c2a 100644 --- a/test/controllers/registration_commands_controller_test.rb +++ b/test/controllers/registration_commands_controller_test.rb @@ -119,6 +119,31 @@ class RegistrationCommandsControllerTest < ActionController::TestCase refute JwtToken.new(parsed_token).decode['exp'] end + + test '0' do + post :create, params: { jwt_expiration: 0 }, session: set_session_user + command = JSON.parse(@response.body)['command'] + parsed_token = command.scan(/(?<=Bearer )(.*)(?=.*)(?=\')/).flatten[0] + refute JwtToken.new(parsed_token).decode['exp'] + end + + test 'value greater than 999999' do + assert_raise Foreman::Exception do + post :create, params: { jwt_expiration: 1000000 }, session: set_session_user + end + end + + test 'value less than 0' do + assert_raise Foreman::Exception do + post :create, params: { jwt_expiration: -1 }, session: set_session_user + end + end + + test 'strings except unlimited' do + assert_raise Foreman::Exception do + post :create, params: { jwt_expiration: 'unlimiteded' }, session: set_session_user + end + end end end