class AlexaRuby::Certificates
SSL certificates validator
Public Class Methods
Setup new certificates chain
@param certificates_chain_url [String] SSL certificates chain URL @param signature [String] HTTP request signature @param request [String] plain HTTP request body
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 13 def initialize(certificates_chain_url, signature, request) download_certificates(certificates_chain_url) @signature = signature @request = request end
Public Instance Methods
Check if it is a valid certificates chain and request signature
@return [Boolean]
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 22 def valid? active? && amazon? && verified? end
Private Instance Methods
Check if it is an active certificate
@return [Boolean]
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 40 def active? now = Time.now (@cert.not_before < now && @cert.not_after > now) || raise( ArgumentError, 'Amazon SSL certificate is outdated ' \ "specified dates: #{@cert.not_before} - #{@cert.not_after}" ) end
Check if Subject Alternative Names includes Amazon domain name
@return [Boolean]
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 53 def amazon? @cert.subject.to_a.flatten.include?('echo-api.amazon.com') || raise( ArgumentError, 'Certificate must be issued for "echo-api.amazon.com" ' \ "(given certificate subject: #{@cert.subject.to_a})" ) end
Decode base64-encoded signature
@return [String] decoded signature
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 80 def decode_signature Base64.decode64(@signature) end
Download SSL certificates chain from Amazon URL
@param certificates_chain_url [String] SSL certificates chain URL
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 31 def download_certificates(certificates_chain_url) resp = HTTParty.get(certificates_chain_url) raise ArgumentError, 'Invalid certificates chain' unless resp.code == 200 @cert = OpenSSL::X509::Certificate.new(resp.body) end
Get hash type for comparison
@return [OpenSSL::Digest::SHA1] OpenSSL SHA1 hash
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 94 def hash OpenSSL::Digest::SHA1.new end
Get public key from certificate
@return [OpenSSL::PKey::RSA] OpenSSL PKey object
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 87 def public_key @cert.public_key end
Check if given signature matches given request
@return [Boolean]
# File lib/alexa_ruby/request/base_request/validator/certificates.rb, line 65 def verified? sign = decode_signature pkey = public_key pkey.verify(hash, sign, @request) || raise( ArgumentError, 'Given request signature does not match with request SHA1 hash ' \ "(signature: #{@signature};\n" \ "request: #{@request})" ) end