class SecureHeaders::Configuration
Constants
- CONFIG_ATTRIBUTES
- CONFIG_ATTRIBUTES_TO_HEADER_CLASSES
- DEFAULT_CONFIG
- HASH_CONFIG_FILE
- HEADERABLE_ATTRIBUTES
The list of attributes that must respond to a `make_header` method
- NOOP_OVERRIDE
- VALIDATABLE_ATTRIBUTES
The list of attributes that must respond to a `validate_config!` method
Public Class Methods
Public: Set the global default configuration.
Optionally supply a block to override the defaults set by this library.
Returns the newly created config.
# File lib/secure_headers/configuration.rb, line 17 def default(&block) if defined?(@default_config) raise AlreadyConfiguredError, "Policy already configured" end # Define a built-in override that clears all configuration options and # results in no security headers being set. override(NOOP_OVERRIDE) do |config| CONFIG_ATTRIBUTES.each do |attr| config.instance_variable_set("@#{attr}", OPT_OUT) end end new_config = new(&block).freeze new_config.validate_config! @default_config = new_config end
# File lib/secure_headers/configuration.rb, line 71 def dup default_config.dup end
# File lib/secure_headers/configuration.rb, line 62 def named_append(name, &block) @appends ||= {} raise "Provide a configuration block" unless block_given? if named_append_or_override_exists?(name) raise AlreadyConfiguredError, "Configuration already exists" end @appends[name] = block end
# File lib/secure_headers/configuration.rb, line 57 def named_appends(name) @appends ||= {} @appends[name] end
# File lib/secure_headers/configuration.rb, line 155 def initialize(&block) @cookies = self.class.send(:deep_copy_if_hash, Cookie::COOKIE_DEFAULTS) @clear_site_data = nil @csp = nil @csp_report_only = nil @hsts = nil @x_content_type_options = nil @x_download_options = nil @x_frame_options = nil @x_permitted_cross_domain_policies = nil @x_xss_protection = nil @expect_certificate_transparency = nil self.referrer_policy = OPT_OUT self.csp = ContentSecurityPolicyConfig.new(ContentSecurityPolicyConfig::DEFAULT) self.csp_report_only = OPT_OUT instance_eval(&block) if block_given? end
Public: create a named configuration that overrides the default config.
name - use an idenfier for the override config. base - override another existing config, or override the default config if no value is supplied.
Returns: the newly created config
# File lib/secure_headers/configuration.rb, line 43 def override(name, &block) @overrides ||= {} raise "Provide a configuration block" unless block_given? if named_append_or_override_exists?(name) raise AlreadyConfiguredError, "Configuration already exists" end @overrides[name] = block end
# File lib/secure_headers/configuration.rb, line 52 def overrides(name) @overrides ||= {} @overrides[name] end
Private Class Methods
Public: perform a basic deep dup. The shallow copy provided by dup/clone can lead to modifying parent objects.
# File lib/secure_headers/configuration.rb, line 84 def deep_copy(config) return unless config config.each_with_object({}) do |(key, value), hash| hash[key] = if value.is_a?(Array) value.dup else value end end end
Private: convenience method purely DRY things up. The value may not be a hash (e.g. OPT_OUT, nil)
# File lib/secure_headers/configuration.rb, line 109 def deep_copy_if_hash(value) if value.is_a?(Hash) deep_copy(value) else value end end
Private: Returns the internal default configuration. This should only ever be called by internal callers (or tests) that know the semantics of ensuring that the default config is never mutated and is dup(ed) before it is used in a request.
# File lib/secure_headers/configuration.rb, line 100 def default_config unless defined?(@default_config) raise NotYetConfiguredError, "Default policy not yet configured" end @default_config end
# File lib/secure_headers/configuration.rb, line 77 def named_append_or_override_exists?(name) (defined?(@appends) && @appends.key?(name)) || (defined?(@overrides) && @overrides.key?(name)) end
Public Instance Methods
# File lib/secure_headers/configuration.rb, line 243 def csp=(new_csp) case new_csp when OPT_OUT @csp = new_csp when ContentSecurityPolicyConfig @csp = new_csp when Hash @csp = ContentSecurityPolicyConfig.new(new_csp) else raise ArgumentError, "Must provide either an existing CSP config or a CSP config hash" end end
Configures the Content-Security-Policy-Report-Only header. `new_csp` cannot contain `report_only: false` or an error will be raised.
NOTE: if csp has not been configured/has the default value when configuring csp_report_only, the code will assume you mean to only use report-only mode and you will be opted-out of enforce mode.
# File lib/secure_headers/configuration.rb, line 262 def csp_report_only=(new_csp) case new_csp when OPT_OUT @csp_report_only = new_csp when ContentSecurityPolicyReportOnlyConfig @csp_report_only = new_csp.dup when ContentSecurityPolicyConfig @csp_report_only = new_csp.make_report_only when Hash @csp_report_only = ContentSecurityPolicyReportOnlyConfig.new(new_csp) else raise ArgumentError, "Must provide either an existing CSP config or a CSP config hash" end end
Public: copy everything
Returns a deep-dup'd copy of this configuration.
# File lib/secure_headers/configuration.rb, line 178 def dup copy = self.class.new copy.cookies = self.class.send(:deep_copy_if_hash, @cookies) copy.csp = @csp.dup if @csp copy.csp_report_only = @csp_report_only.dup if @csp_report_only copy.x_content_type_options = @x_content_type_options copy.hsts = @hsts copy.x_frame_options = @x_frame_options copy.x_xss_protection = @x_xss_protection copy.x_download_options = @x_download_options copy.x_permitted_cross_domain_policies = @x_permitted_cross_domain_policies copy.clear_site_data = @clear_site_data copy.expect_certificate_transparency = @expect_certificate_transparency copy.referrer_policy = @referrer_policy copy end
# File lib/secure_headers/configuration.rb, line 207 def generate_headers headers = {} HEADERABLE_ATTRIBUTES.each do |attr| klass = CONFIG_ATTRIBUTES_TO_HEADER_CLASSES[attr] header_name, value = klass.make_header(instance_variable_get("@#{attr}")) if header_name && value headers[header_name] = value end end headers end
# File lib/secure_headers/configuration.rb, line 219 def opt_out(header) send("#{header}=", OPT_OUT) end
Public: Apply a named override to the current config
Returns self
# File lib/secure_headers/configuration.rb, line 198 def override(name = nil, &block) if override = self.class.overrides(name) instance_eval(&override) else raise ArgumentError.new("no override by the name of #{name} has been configured") end self end
# File lib/secure_headers/configuration.rb, line 223 def update_x_frame_options(value) @x_frame_options = value end
Public: validates all configurations values.
Raises various configuration errors if any invalid config is detected.
Returns nothing
# File lib/secure_headers/configuration.rb, line 232 def validate_config! VALIDATABLE_ATTRIBUTES.each do |attr| klass = CONFIG_ATTRIBUTES_TO_HEADER_CLASSES[attr] klass.validate_config!(instance_variable_get("@#{attr}")) end end