Class: Rhales::CSP
- Inherits:
-
Object
- Object
- Rhales::CSP
- Defined in:
- lib/rhales/csp.rb
Overview
Content Security Policy (CSP) header generation and management
Provides secure defaults and nonce integration for CSP headers. Converts policy configuration into proper CSP header strings.
Usage: csp = Rhales::CSP.new(config, nonce: ‘abc123’) header = csp.build_header # => “default-src ‘self’; script-src ‘self’ ‘nonce-abc123’; …”
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#nonce ⇒ Object
readonly
Returns the value of attribute nonce.
Class Method Summary collapse
-
.generate_nonce ⇒ Object
Generate a new nonce value.
Instance Method Summary collapse
-
#build_header ⇒ Object
Build CSP header string from configuration.
-
#initialize(config, nonce: nil) ⇒ CSP
constructor
A new instance of CSP.
-
#interpolate_nonce(source) ⇒ Object
private
Interpolate nonce placeholder in source values.
-
#nonce_required? ⇒ Boolean
Check if nonce is required for any directive.
-
#validate_policy! ⇒ Object
Validate CSP policy configuration.
Constructor Details
#initialize(config, nonce: nil) ⇒ CSP
Returns a new instance of CSP.
16 17 18 19 |
# File 'lib/rhales/csp.rb', line 16 def initialize(config, nonce: nil) @config = config @nonce = nonce end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
14 15 16 |
# File 'lib/rhales/csp.rb', line 14 def config @config end |
#nonce ⇒ Object (readonly)
Returns the value of attribute nonce.
14 15 16 |
# File 'lib/rhales/csp.rb', line 14 def nonce @nonce end |
Class Method Details
.generate_nonce ⇒ Object
Generate a new nonce value
43 44 45 |
# File 'lib/rhales/csp.rb', line 43 def self.generate_nonce SecureRandom.hex(16) end |
Instance Method Details
#build_header ⇒ Object
Build CSP header string from configuration
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/rhales/csp.rb', line 22 def build_header return nil unless @config.csp_enabled policy_directives = [] @config.csp_policy.each do |directive, sources| if sources.empty? # For directives with no sources (like upgrade-insecure-requests) policy_directives << directive else # Process sources and interpolate nonce if present processed_sources = sources.map { |source| interpolate_nonce(source) } directive_string = "#{directive} #{processed_sources.join(' ')}" policy_directives << directive_string end end policy_directives.join('; ') end |
#interpolate_nonce(source) ⇒ Object (private)
Interpolate nonce placeholder in source values
88 89 90 91 92 |
# File 'lib/rhales/csp.rb', line 88 def interpolate_nonce(source) return source unless @nonce && source.include?('{{nonce}}') source.gsub('{{nonce}}', @nonce) end |
#nonce_required? ⇒ Boolean
Check if nonce is required for any directive
79 80 81 82 83 |
# File 'lib/rhales/csp.rb', line 79 def nonce_required? return false unless @config.csp_enabled @config.csp_policy.values.flatten.any? { |source| source.include?('{{nonce}}') } end |
#validate_policy! ⇒ Object
Validate CSP policy configuration
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rhales/csp.rb', line 48 def validate_policy! return unless @config.csp_enabled errors = [] # Ensure policy is a hash unless @config.csp_policy.is_a?(Hash) errors << 'csp_policy must be a hash' raise Rhales::Configuration::ConfigurationError, "CSP policy errors: #{errors.join(', ')}" end # Validate each directive @config.csp_policy.each do |directive, sources| unless sources.is_a?(Array) errors << "#{directive} sources must be an array" end # Check for dangerous sources if sources.include?("'unsafe-eval'") errors << "#{directive} contains dangerous 'unsafe-eval' source" end if sources.include?("'unsafe-inline'") && !%w[style-src].include?(directive) errors << "#{directive} contains dangerous 'unsafe-inline' source" end end raise Rhales::Configuration::ConfigurationError, "CSP policy errors: #{errors.join(', ')}" unless errors.empty? end |