module AlexaVerifier::CertificateStore

A module used to download, cache and serve certificates from our requests. @since 0.1

Constants

CERTIFICATE_CACHE_TIME
CERTIFICATE_SEPARATOR

Public Class Methods

delete(uri) click to toggle source

Given a certificate uri, remove the certificate from our store.

@param [String] uri the uri of our certificate @return [nil|Hash] returns nil if the certificate was not in the store,

or a Hash representing the deleted certificate
# File lib/alexa_verifier/certificate_store.rb, line 35
def delete(uri)
  store

  @store.delete(uri)
end
fetch(uri) click to toggle source

Given a certificate uri, either download the certificate and chain, or load them from our certificate store.

@param [String] uri the uri of our certificate @return [OpenSSL::X509::Certificate, Array<OpenSSL::X509::Certificate>] our certificate file and chain

# File lib/alexa_verifier/certificate_store.rb, line 14
def fetch(uri)
  store

  if cache_valid?(@store[uri])
    certificate = @store[uri][:certificate]
    chain = @store[uri][:chain]
  else
    chain = generate_certificate_chain_from_data(download_certificate(uri))
    certificate = chain.delete_at(0)

    @store[uri] = { timestamp: Time.now, certificate: certificate, chain: chain }
  end

  [certificate, chain]
end
store() click to toggle source

Returns a copy of our certificate store

@return [Hash] returns our certificate store

# File lib/alexa_verifier/certificate_store.rb, line 44
def store
  @store ||= {}
end

Private Class Methods

cache_valid?(certificate_entry) click to toggle source

Given a certificate entry from our store, tell us if the cache is still valid

@param [Hash] certificate_entry the entry we are checking @return [Boolean] is the certificate cache valid?

# File lib/alexa_verifier/certificate_store.rb, line 54
def cache_valid?(certificate_entry)
  return false if certificate_entry.nil?

  (Time.now <= (certificate_entry[:timestamp] + CERTIFICATE_CACHE_TIME))
end
download_certificate(uri) click to toggle source

Given a certificate uri, download it and return the certificate data

@param [String] uri the uri of our certificates @return [String] certificate data

# File lib/alexa_verifier/certificate_store.rb, line 64
def download_certificate(uri)
  certificate_uri = URI.parse(uri)

  certificate_data = nil

  Net::HTTP.start(certificate_uri.host, certificate_uri.port, use_ssl: true) do |http|
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER

    response = http.request(Net::HTTP::Get.new(certificate_uri))

    raise AlexaVerifier::InvalidCertificateError, "Unable to download certificate from #{certificate_uri} - Got #{response.code} status code" unless response.is_a? Net::HTTPOK

    certificate_data = response.body
  end

  certificate_data
end
generate_certificate_chain_from_data(certificate_data) click to toggle source

Given a string of certificate data, which may contain one or more certificates, convert it into an array of certificate object representing the full chain.

@param [String] certificate_data the certificate data we should build our chain from @return [Array<OpenSSL::X509::Certificate>] an array of certificate objects representing our chain

# File lib/alexa_verifier/certificate_store.rb, line 87
def generate_certificate_chain_from_data(certificate_data)
  split_data = certificate_data.split(CERTIFICATE_SEPARATOR)

  # Remove any empty string artifacts
  split_data.reject! { |data| data.strip.empty? }

  # Convert our array of split out certificate data strings, into an array of certificate objects
  split_data.map { |data| OpenSSL::X509::Certificate.new(CERTIFICATE_SEPARATOR + data) }
end