Class: SecureHeaders::PublicKeyPins

Inherits:
Object
  • Object
show all
Defined in:
lib/secure_headers/headers/public_key_pins.rb

Constant Summary collapse

HEADER_NAME =
"Public-Key-Pins".freeze
REPORT_ONLY =
"Public-Key-Pins-Report-Only".freeze
HASH_ALGORITHMS =
[:sha256].freeze
CONFIG_KEY =
:hpkp

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ PublicKeyPins

Returns a new instance of PublicKeyPins.



35
36
37
38
39
40
41
# File 'lib/secure_headers/headers/public_key_pins.rb', line 35

def initialize(config)
  @max_age = config.fetch(:max_age, nil)
  @pins = config.fetch(:pins, nil)
  @report_uri = config.fetch(:report_uri, nil)
  @report_only = !!config.fetch(:report_only, nil)
  @include_subdomains = !!config.fetch(:include_subdomains, nil)
end

Class Method Details

.make_header(config) ⇒ Object

Public: make an hpkp header name, value pair

Returns nil if not configured, returns header name and value if configured.



14
15
16
17
18
# File 'lib/secure_headers/headers/public_key_pins.rb', line 14

def make_header(config)
  return if config.nil?
  header = new(config)
  [header.name, header.value]
end

.validate_config!(config) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/secure_headers/headers/public_key_pins.rb', line 20

def validate_config!(config)
  return if config.nil? || config == OPT_OUT
  raise PublicKeyPinsConfigError.new("config must be a hash.") unless config.is_a? Hash

  if !config[:max_age]
    raise PublicKeyPinsConfigError.new("max-age is a required directive.")
  elsif config[:max_age].to_s !~ /\A\d+\z/
    raise PublicKeyPinsConfigError.new("max-age must be a number.
                                      #{config[:max_age]} was supplied.")
  elsif config[:pins] && config[:pins].length < 2
    raise PublicKeyPinsConfigError.new("A minimum of 2 pins are required.")
  end
end

Instance Method Details

#max_age_directiveObject



69
70
71
# File 'lib/secure_headers/headers/public_key_pins.rb', line 69

def max_age_directive
  "max-age=#{@max_age}" if @max_age
end

#nameObject



43
44
45
46
47
48
49
# File 'lib/secure_headers/headers/public_key_pins.rb', line 43

def name
  if @report_only
    REPORT_ONLY
  else
    HEADER_NAME
  end
end

#pin_directivesObject



60
61
62
63
64
65
66
67
# File 'lib/secure_headers/headers/public_key_pins.rb', line 60

def pin_directives
  return nil if @pins.nil?
  @pins.collect do |pin|
    pin.map do |token, hash|
      "pin-#{token}=\"#{hash}\"" if HASH_ALGORITHMS.include?(token)
    end
  end.join('; ')
end

#report_uri_directiveObject



73
74
75
# File 'lib/secure_headers/headers/public_key_pins.rb', line 73

def report_uri_directive
  "report-uri=\"#{@report_uri}\"" if @report_uri
end

#subdomain_directiveObject



77
78
79
# File 'lib/secure_headers/headers/public_key_pins.rb', line 77

def subdomain_directive
  @include_subdomains ? 'includeSubDomains' : nil
end

#valueObject



51
52
53
54
55
56
57
58
# File 'lib/secure_headers/headers/public_key_pins.rb', line 51

def value
  header_value = [
    max_age_directive,
    pin_directives,
    report_uri_directive,
    subdomain_directive
  ].compact.join('; ').strip
end