diff --git a/app/models/manageiq/providers/kubernetes/container_manager.rb b/app/models/manageiq/providers/kubernetes/container_manager.rb index b878f34846..494b015305 100644 --- a/app/models/manageiq/providers/kubernetes/container_manager.rb +++ b/app/models/manageiq/providers/kubernetes/container_manager.rb @@ -14,6 +14,7 @@ class ManageIQ::Providers::Kubernetes::ContainerManager < ManageIQ::Providers::C require_nested :Scanning include ManageIQ::Providers::Kubernetes::ContainerManagerMixin + extend ManageIQ::Providers::Kubernetes::ContainerManager::Options # See HasMonitoringManagerMixin has_one :monitoring_manager, diff --git a/app/models/manageiq/providers/kubernetes/container_manager/options.rb b/app/models/manageiq/providers/kubernetes/container_manager/options.rb new file mode 100644 index 0000000000..0ff033fbba --- /dev/null +++ b/app/models/manageiq/providers/kubernetes/container_manager/options.rb @@ -0,0 +1,73 @@ +module ManageIQ::Providers::Kubernetes::ContainerManager::Options + extend ActiveSupport::Concern + + def proxy_settings + { + :http_proxy => { + :label => N_('HTTP Proxy'), + :help_text => N_('HTTP Proxy to connect ManageIQ to the provider. example: http://user:password@my_https_proxy'), + :global_default => VMDB::Util.http_proxy_uri, + }, + } + end + + def advanced_settings + { + :image_inspector_options => { + :label => N_('Image Inspector Options'), + :help_text => N_('Settings for Image Inspector tool'), + :settings => { + :http_proxy => { + :label => N_('HTTP Proxy'), + :help_text => N_('HTTP Proxy to connect image inspector pods to the internet. example: http://user:password@my_https_proxy'), + }, + :https_proxy => { + :label => N_('HTTPS Proxy'), + :help_text => N_('HTTPS Proxy to connect image inspector pods to the internet. example: https://user:password@my_https_proxy'), + }, + :no_proxy => { + :label => N_('NO Proxy'), + :help_text => N_('NO Proxy lists urls that should\'nt be sent to any proxy. example: my_file_server.org'), + }, + :repository => { + :label => N_('Image-Inspector Repository'), + :help_text => N_('Image-Inspector Repository. example: openshift/image-inspector'), + :global_default => Settings.ems.ems_kubernetes.image_inspector_repository, + }, + :registry => { + :label => N_('Image-Inspector Registry'), + :help_text => N_('Registry to provide the image inspector repository. example: docker.io'), + :global_default => Settings.ems.ems_kubernetes.image_inspector_registry, + }, + :image_tag => { + :label => N_('Image-Inspector Tag'), + :help_text => N_('Image-Inspector image tag. example: 2.1'), + :global_default => ManageIQ::Providers::Kubernetes::ContainerManager::Scanning::Job::INSPECTOR_IMAGE_TAG, + }, + :cve_url => { + :label => N_('CVE location'), + :help_text => N_('Enables defining a URL path prefix for XCCDF file instead of accessing the default location. +example: http://my_file_server.org:3333/xccdf_files/ +Expecting to find com.redhat.rhsa-RHEL7.ds.xml.bz2 file there.'), + # Future versions of image inspector will extend this. + }, + } + } + } + end + + def provider_settings + { + :proxy_settings => { + :label => N_('Proxy Settings'), + :help_text => N_('Proxy Settings for connection to the provider'), + :settings => proxy_settings, + }, + :advanced_settings => { + :label => N_('Advanced Settings'), + :help_text => N_('Advanced Settings for provider configuration'), + :settings => advanced_settings, + } + } + end +end diff --git a/app/models/manageiq/providers/kubernetes/container_manager/scanning/job.rb b/app/models/manageiq/providers/kubernetes/container_manager/scanning/job.rb index 16182b108f..5f4afbfb28 100644 --- a/app/models/manageiq/providers/kubernetes/container_manager/scanning/job.rb +++ b/app/models/manageiq/providers/kubernetes/container_manager/scanning/job.rb @@ -13,7 +13,6 @@ class ManageIQ::Providers::Kubernetes::ContainerManager::Scanning::Job < Job ERRCODE_NOTFOUND = 404 IMAGE_INSPECTOR_SA = 'inspector-admin' INSPECTOR_ADMIN_SECRET_PATH = '/var/run/secrets/kubernetes.io/inspector-admin-secret-' - ATTRIBUTE_SECTION = 'cluster_settings' PROXY_ENV_VARIABLES = %w(no_proxy http_proxy https_proxy) def load_transitions @@ -347,6 +346,10 @@ def inspector_admin_secret return nil end + def ems_options + @provider_options ||= ext_management_system.options.try(:fetch_path, :image_inspector_options) || {} + end + def pod_definition(inspector_admin_secret_name) pod_def = { :apiVersion => "v1", @@ -409,6 +412,7 @@ def pod_definition(inspector_admin_secret_name) } add_secret_to_pod_def(pod_def, inspector_admin_secret_name) unless inspector_admin_secret_name.blank? + add_cve_url(pod_def) Kubeclient::Resource.new(pod_def) end @@ -425,17 +429,25 @@ def add_secret_to_pod_def(pod_def, inspector_admin_secret_name) end def inspector_image - registry = ::Settings.ems.ems_kubernetes.image_inspector_registry - repo = ::Settings.ems.ems_kubernetes.image_inspector_repository - "#{registry}/#{repo}:#{INSPECTOR_IMAGE_TAG}" + registry = ems_options.fetch_path(:registry) || ::Settings.ems.ems_kubernetes.image_inspector_registry + repo = ems_options.fetch_path(:repository) || ::Settings.ems.ems_kubernetes.image_inspector_repository + tag = ems_options.fetch_path(:image_tag) || INSPECTOR_IMAGE_TAG + "#{registry}/#{repo}:#{tag}" end def inspector_proxy_env_variables - settings = ext_management_system.custom_attributes - settings.where(:section => ATTRIBUTE_SECTION, - :name => PROXY_ENV_VARIABLES).each_with_object([]) do |att, env| - env << {:name => att.name.upcase, - :value => att.value} unless att.value.blank? + PROXY_ENV_VARIABLES.each_with_object([]) do |var_name, env| + if ems_options.key?(var_name.to_sym) + var_value = ems_options[var_name.to_sym] + env << {:name => var_name.upcase, + :value => var_value} + end + end + end + + def add_cve_url(pod_def) + if ems_options.key?(:cve_url) + pod_def[:spec][:containers][0][:command].append("--cve-url=#{ems_options[:cve_url]}") end end end diff --git a/app/models/manageiq/providers/kubernetes/container_manager_mixin.rb b/app/models/manageiq/providers/kubernetes/container_manager_mixin.rb index 1e03507adc..62f7d1a9ae 100644 --- a/app/models/manageiq/providers/kubernetes/container_manager_mixin.rb +++ b/app/models/manageiq/providers/kubernetes/container_manager_mixin.rb @@ -42,7 +42,7 @@ def kubernetes_connect(hostname, port, options) options[:version] || kubernetes_version, :ssl_options => Kubeclient::Client::DEFAULT_SSL_OPTIONS.merge(options[:ssl_options] || {}), :auth_options => kubernetes_auth_options(options), - :http_proxy_uri => VMDB::Util.http_proxy_uri, + :http_proxy_uri => options[:http_proxy] || VMDB::Util.http_proxy_uri, :timeouts => { :open => Settings.ems.ems_kubernetes.open_timeout.to_f_with_method, :read => Settings.ems.ems_kubernetes.read_timeout.to_f_with_method @@ -108,11 +108,12 @@ def ssl_cert_store(endpoint = default_endpoint) def connect(options = {}) effective_options = options.merge( - :hostname => options[:hostname] || address, - :port => options[:port] || port, - :user => options[:user] || authentication_userid(options[:auth_type]), - :pass => options[:pass] || authentication_password(options[:auth_type]), - :bearer => options[:bearer] || authentication_token(options[:auth_type] || 'bearer'), + :hostname => options[:hostname] || address, + :port => options[:port] || port, + :user => options[:user] || authentication_userid(options[:auth_type]), + :pass => options[:pass] || authentication_password(options[:auth_type]), + :bearer => options[:bearer] || authentication_token(options[:auth_type] || 'bearer'), + :http_proxy => self.options ? self.options.fetch_path(:proxy_settings, :http_proxy) : nil, :ssl_options => options[:ssl_options] || { :verify_ssl => verify_ssl_mode, :cert_store => ssl_cert_store diff --git a/spec/models/manageiq/providers/kubernetes/container_manager/scanning/job_spec.rb b/spec/models/manageiq/providers/kubernetes/container_manager/scanning/job_spec.rb index 4ba4859026..2d04283ddf 100644 --- a/spec/models/manageiq/providers/kubernetes/container_manager/scanning/job_spec.rb +++ b/spec/models/manageiq/providers/kubernetes/container_manager/scanning/job_spec.rb @@ -190,18 +190,30 @@ def fetch_oscap_arf end end - it 'should add correct environment variables' do - att_name = 'http_proxy' - my_value = "MY_TEST_VALUE" - @ems.custom_attributes.create(:section => described_class::ATTRIBUTE_SECTION, - :name => att_name, - :value => my_value) - allow_any_instance_of(described_class).to receive_messages(:kubernetes_client => MockKubeClient.new) - kc = @job.kubernetes_client - secret_name = kc.get_service_account[:imagePullSecrets][0][:name] - pod = @job.send(:pod_definition, secret_name) - expect(pod[:spec][:containers][0][:env][0][:name]).to eq(att_name.upcase) - expect(pod[:spec][:containers][0][:env][0][:value]).to eq(my_value) + context "using provider options" do + def get_pod_definition + allow_any_instance_of(described_class).to receive_messages(:kubernetes_client => MockKubeClient.new) + kc = @job.kubernetes_client + secret_name = kc.get_service_account[:imagePullSecrets][0][:name] + @job.send(:pod_definition, secret_name) + end + + it 'should add correct environment variables from options' do + att_name = 'http_proxy' + my_value = "MY_TEST_VALUE" + @ems.update(:options => { :image_inspector_options => {att_name.to_sym => my_value} }) + pod = get_pod_definition + expect(pod[:spec][:containers][0][:env][0][:name]).to eq(att_name.upcase) + expect(pod[:spec][:containers][0][:env][0][:value]).to eq(my_value) + end + + it 'should send cve_url from options' do + cve_url_value = "get_cve_from_here.com" + @ems.update(:options => { :image_inspector_options => {:cve_url => cve_url_value} }) + pod = get_pod_definition + expect(pod[:spec][:containers][0][:command] + .select { |cmd| cmd.starts_with?("--cve-url=")}.first.split('=').last).to eq(cve_url_value) + end end it 'should send correct dockercfg secrets' do diff --git a/spec/models/manageiq/providers/kubernetes/container_manager_spec.rb b/spec/models/manageiq/providers/kubernetes/container_manager_spec.rb index 2335ca83d3..bffc1ba2e9 100644 --- a/spec/models/manageiq/providers/kubernetes/container_manager_spec.rb +++ b/spec/models/manageiq/providers/kubernetes/container_manager_spec.rb @@ -172,6 +172,24 @@ ) described_class.raw_connect(hostname, port, options) end + + it "connect uses provider options for http_proxy" do + allow(VMDB::Util).to receive(:http_proxy_uri).and_return(URI::HTTP.build(:host => "some")) + require 'kubeclient' + my_proxy_value = "internal_proxy.org" + expect(Kubeclient::Client).to receive(:new).with( + instance_of(URI::HTTPS), 'v1', + hash_including(:http_proxy_uri => my_proxy_value) + ) + ems = FactoryGirl.create( + :ems_kubernetes, + :endpoints => [ + FactoryGirl.create(:endpoint, :role => 'default', :hostname => 'host'), + FactoryGirl.create(:endpoint, :role => 'prometheus_alerts', :hostname => 'host2'), + ]) + ems.update(:options => {:proxy_settings => {:http_proxy => my_proxy_value}}) + ems.connect + end end # Test MonitoringManager functionality related to ContainerManager