diff --git a/app/controllers/compute_resources_vms_controller.rb b/app/controllers/compute_resources_vms_controller.rb index e774acf6c27..b17006fe898 100644 --- a/app/controllers/compute_resources_vms_controller.rb +++ b/app/controllers/compute_resources_vms_controller.rb @@ -78,14 +78,7 @@ def console @compute_resource = find_compute_resource(:console_compute_resources_vms) @vm = find_vm @console = @compute_resource.console @vm.identity - @encrypt = case Setting[:websockets_encrypt] - when 'on' - true - when 'off' - false - else - request.ssl? and not Setting[:websockets_ssl_key].blank? and not Setting[:websockets_ssl_cert].blank? - end + @encrypt = Setting[:websockets_encrypt] render case @console[:type] when 'spice' "hosts/console/spice" diff --git a/app/controllers/hosts_controller.rb b/app/controllers/hosts_controller.rb index 016136d56d4..1e8e82b08e9 100644 --- a/app/controllers/hosts_controller.rb +++ b/app/controllers/hosts_controller.rb @@ -288,14 +288,7 @@ def ipmi_boot def console return unless @host.compute_resource @console = @host.compute_resource.console @host.uuid - @encrypt = case Setting[:websockets_encrypt] - when 'on' - true - when 'off' - false - else - request.ssl? and not Setting[:websockets_ssl_key].blank? and not Setting[:websockets_ssl_cert].blank? - end + @encrypt = Setting[:websockets_encrypt] render case @console[:type] when 'spice' "hosts/console/spice" diff --git a/app/models/setting.rb b/app/models/setting.rb index b8512ecac11..3836665f5f0 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -18,6 +18,12 @@ def validate_each(record, attribute, value) end end + class ValueValidator < ActiveModel::Validator + def validate(record) + record.send("validate_#{record.name}", record) + end + end + attr_accessible :name, :value, :description, :category, :settings_type, :default validates_lengths_from_database @@ -34,6 +40,7 @@ def validate_each(record, attribute, value) validates :value, :presence => true, :if => Proc.new {|s| s.settings_type == "array" && !BLANK_ATTRS.include?(s.name) } validates :settings_type, :inclusion => {:in => TYPES}, :allow_nil => true, :allow_blank => true validates :value, :uri => true, :presence => true, :if => Proc.new {|s| URI_ATTRS.include?(s.name) } + validates_with ValueValidator, :if => Proc.new {|s| s.respond_to?("validate_#{s.name}") } before_validation :set_setting_type_from_value before_save :clear_value_when_default before_save :clear_cache diff --git a/app/models/setting/auth.rb b/app/models/setting/auth.rb index 5dcbf0ba86e..93c644df007 100644 --- a/app/models/setting/auth.rb +++ b/app/models/setting/auth.rb @@ -24,7 +24,7 @@ def self.load_defaults self.set('ssl_priv_key', N_("SSL Private Key file that Foreman will use to communicate with its proxies"), ssl_priv_key), self.set('ssl_client_dn_env', N_('Environment variable containing the subject DN from a client SSL certificate'), 'SSL_CLIENT_S_DN'), self.set('ssl_client_verify_env', N_('Environment variable containing the verification status of a client SSL certificate'), 'SSL_CLIENT_VERIFY'), - self.set('websockets_encrypt', N_("Should Foreman encrypt websockets (VNC console access). Choose on, off or auto."), "auto"), + self.set('websockets_encrypt', N_("VNC/SPICE websocket proxy console access encryption (websockets_ssl_key/cert setting required)"), SETTINGS[:require_ssl]), self.set('websockets_ssl_key', N_("Private key that Foreman will use to encrypt websockets "), nil), self.set('websockets_ssl_cert', N_("Certificate that Foreman will use to encrypt websockets "), nil), self.set('login_delegation_logout_url', N_('Redirect your users to this url on logout (authorize_login_delegation should also be enabled)'), nil), @@ -37,4 +37,22 @@ def self.load_defaults true end + + def validate_websockets_encrypt(record) + if record.value && (Setting["websockets_ssl_key"].empty? || Setting["websockets_ssl_cert"].empty?) + record.errors[:base] << _("Unable to turn on websockets_encrypt, either websockets_ssl_key or websockets_ssl_cert is missing") + end + end + + def validate_websockets_ssl_key(record) + if record.value.empty? && Setting["websockets_encrypt"] + record.errors[:base] << _("Unable to unset websockets_ssl_key when websockets_encrypt is on") + end + end + + def validate_websockets_ssl_cert(record) + if record.value.empty? && Setting["websockets_encrypt"] + record.errors[:base] << _("Unable to unset websockets_ssl_cert when websockets_encrypt is on") + end + end end diff --git a/db/migrate/20150312144232_migrate_websockets_setting.rb b/db/migrate/20150312144232_migrate_websockets_setting.rb new file mode 100644 index 00000000000..f7516b22dd1 --- /dev/null +++ b/db/migrate/20150312144232_migrate_websockets_setting.rb @@ -0,0 +1,19 @@ +class MigrateWebsocketsSetting < ActiveRecord::Migration + def up + return unless encrypt = Setting.find_by_name("websockets_encrypt") + encrypt.settings_type = "boolean" + if encrypt.value == "auto" + encrypt.value = (Setting[:websockets_ssl_key].nil? || + Setting[:websockets_ssl_cert].nil?) ? false : true + else + encrypt.value = Foreman::Cast.to_bool(encrypt.value) + end + encrypt.default = false + encrypt.save(:validate => false) + end + + def down + # delete and reset on next app server start + Setting.delete_by_name("websockets_encrypt") + end +end diff --git a/lib/ws_proxy.rb b/lib/ws_proxy.rb index 770e733c0b7..af405403dfc 100644 --- a/lib/ws_proxy.rb +++ b/lib/ws_proxy.rb @@ -43,8 +43,10 @@ def start_proxy begin cmd = "#{ws_proxy} --daemon --idle-timeout=#{idle_timeout} --timeout=#{timeout} #{port} #{host}:#{host_port}" cmd += " --ssl-target" if ssl_target - cmd += " --cert #{Setting[:websockets_ssl_cert]}" if Setting[:websockets_ssl_cert] - cmd += " --key #{Setting[:websockets_ssl_key]}" if Setting[:websockets_ssl_key] + if Setting[:websockets_encrypt] + cmd += " --cert #{Setting[:websockets_ssl_cert]}" if Setting[:websockets_ssl_cert] + cmd += " --key #{Setting[:websockets_ssl_key]}" if Setting[:websockets_ssl_key] + end execute(cmd) rescue PortInUse # fallback just in case of race condition