From b2066945c8bbbe0fb611cdb0dfc399a3cbd1a3de Mon Sep 17 00:00:00 2001 From: Bill Wei Date: Tue, 4 Apr 2017 11:44:33 -0400 Subject: [PATCH] Parse password field from dialog and decryt before job launch https://bugzilla.redhat.com/show_bug.cgi?id=1438923 --- app/models/service_ansible_playbook.rb | 17 ++++++----- spec/models/service_ansible_playbook_spec.rb | 31 ++++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/app/models/service_ansible_playbook.rb b/app/models/service_ansible_playbook.rb index d20f594ef4d..ed18f35fe1c 100644 --- a/app/models/service_ansible_playbook.rb +++ b/app/models/service_ansible_playbook.rb @@ -13,7 +13,7 @@ def execute(action) hosts = opts.delete(:hosts) _log.info("Launching Ansible Tower job with options: #{opts}") - new_job = ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Job.create_job(jt, opts) + new_job = ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Job.create_job(jt, decrypt_options(opts)) update_job_for_playbook(action, new_job, hosts) _log.info("Ansible Tower job with ref #{new_job.ems_ref} was created.") @@ -69,10 +69,7 @@ def request_options_extra_vars end def get_job_options(action) - job_opts = options[job_option_key(action)].deep_dup - - # TODO: decryption may be needed - job_opts + options[job_option_key(action)].deep_dup end def save_job_options(action, overrides) @@ -86,7 +83,6 @@ def save_job_options(action, overrides) hosts = job_options[:hosts] job_options[:inventory] = create_inventory_with_hosts(action, hosts).id unless use_default_inventory?(hosts) - # TODO: encryption my be needed options[job_option_key(action)] = job_options save! end @@ -107,7 +103,8 @@ def parse_dialog_options def extra_vars_from_dialog params = (options[:dialog] || {}).each_with_object({}) do |(attr, val), obj| - obj[attr.sub('dialog_param_', '')] = val if attr =~ /dialog_param_/ + var_key = attr.sub(/^(password::)?dialog_param_/, '') + obj[var_key] = val unless var_key == attr end params.blank? ? {} : {:extra_vars => params} @@ -151,4 +148,10 @@ def update_job_for_playbook(action, job, hosts) playbook_id = options.fetch_path(:config_info, action.downcase.to_sym, :playbook_id) job.update_attributes(:configuration_script_base_id => playbook_id, :hosts => host_array) end + + def decrypt_options(opts) + opts.tap do + opts[:extra_vars].transform_values! { |val| val.kind_of?(String) ? MiqPassword.try_decrypt(val) : val } + end + end end diff --git a/spec/models/service_ansible_playbook_spec.rb b/spec/models/service_ansible_playbook_spec.rb index e7faa647074..e82e831ce78 100644 --- a/spec/models/service_ansible_playbook_spec.rb +++ b/spec/models/service_ansible_playbook_spec.rb @@ -7,6 +7,9 @@ let(:credential_0) { FactoryGirl.create(:authentication, :manager_ref => '1') } let(:credential_1) { FactoryGirl.create(:authentication, :manager_ref => 'a') } let(:credential_2) { FactoryGirl.create(:authentication, :manager_ref => 'b') } + let(:decrpyted_val) { 'my secret' } + let(:encrypted_val) { MiqPassword.encrypt(decrpyted_val) } + let(:encrypted_val2) { MiqPassword.encrypt(decrpyted_val + "new") } let(:loaded_service) do service_template = FactoryGirl.create(:service_template_ansible_playbook) @@ -26,10 +29,11 @@ let(:dialog_options) do { :dialog => { - 'dialog_hosts' => 'host1,host2', - 'dialog_credential' => credential_1.id, - 'dialog_param_var1' => 'value1', - 'dialog_param_var2' => 'value2' + 'dialog_hosts' => 'host1,host2', + 'dialog_credential' => credential_1.id, + 'dialog_param_var1' => 'value1', + 'dialog_param_var2' => 'value2', + 'password::dialog_param_pswd' => encrypted_val } } end @@ -55,7 +59,7 @@ { :credential_id => credential_2.id, :hosts => 'host3', - :extra_vars => { 'var1' => 'new_val1' } + :extra_vars => { 'var1' => 'new_val1', 'pswd' => encrypted_val2 } } end @@ -65,7 +69,7 @@ :credential => 1, :inventory => 2, :hosts => "default_host1,default_host2", - :extra_vars => {'var1' => 'value1', 'var2' => 'value2'} + :extra_vars => {'var1' => 'value1', 'var2' => 'value2', 'pswd' => encrypted_val} } } end @@ -90,7 +94,7 @@ expect(service.options[:provision_job_options]).to have_attributes( :inventory => 20, :credential => credential_1.manager_ref, - :extra_vars => {'var1' => 'value1', 'var2' => 'value2', 'var3' => 'default_val3'} + :extra_vars => {'var1' => 'value1', 'var2' => 'value2', 'var3' => 'default_val3', 'pswd' => encrypted_val} ) end @@ -126,18 +130,18 @@ expect(service.options[:provision_job_options]).to have_attributes( :inventory => 30, :credential => credential_2.manager_ref, - :extra_vars => {'var1' => 'new_val1', 'var2' => 'value2', 'var3' => 'default_val3'} + :extra_vars => {'var1' => 'new_val1', 'var2' => 'value2', 'var3' => 'default_val3', 'pswd' => encrypted_val2} ) end end end describe '#execute' do + let(:control_extras) { {'a' => 'A', 'b' => 'B', 'c' => 'C'} } before do FactoryGirl.create(:miq_region, :region => ApplicationRecord.my_region_number) miq_request_task = FactoryGirl.create(:miq_request_task) - @control_extras = { 'a' => 'A', 'b' => 'B', 'c' => 'C'} - miq_request_task.update_attributes(:options => {:request_options => {:manageiq_extra_vars => @control_extras}}) + miq_request_task.update_attributes(:options => {:request_options => {:manageiq_extra_vars => control_extras}}) loaded_service.update_attributes(:evm_owner => FactoryGirl.create(:user), :miq_request_task => miq_request_task) end @@ -145,9 +149,12 @@ it 'creates an Ansible Tower job' do expect(ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Job).to receive(:create_job) do |jobtemp, opts| expect(jobtemp).to eq(tower_job_temp) - exposed_miq = %w(api_url api_token service user) + @control_extras.keys + exposed_miq = %w(api_url api_token service user) + control_extras.keys expect(opts[:extra_vars].delete('manageiq').keys).to include(*exposed_miq) - expect(opts).to include(provision_options[:provision_job_options].except(:hosts)) + + expected_opts = provision_options[:provision_job_options].except(:hosts) + expected_opts[:extra_vars]['pswd'] = decrpyted_val + expect(opts).to include(expected_opts) tower_job end loaded_service.execute(action)