class AWS::SNS::Message

Represents a single SNS message.

See also docs.aws.amazon.com/sns/latest/gsg/json-formats.html

Originators

Originators are sources of SNS messages. {FromAutoScaling} is one. {Message} can be extended by originators if their applicable? method returns true when passed the raw message. Originator modules must implement ‘applicable? sns` module function. If an originator is applicable, it should set the `@origin` accessor to denote itself.

Constants

SIGNABLE_KEYS

Attributes

origin[RW]
raw[R]

Public Class Methods

new(sns) click to toggle source

@return {Message} Constructs a new {Message} from the raw SNS, sets origin

# File lib/aws/sns/message.rb, line 55
def initialize sns
  if sns.is_a? String
    @raw = parse_from sns
  else
    @raw = sns
  end
  @origin = :sns
  self.extend FromAutoScaling if FromAutoScaling.applicable? @raw
end

Public Instance Methods

[](key) click to toggle source

@param [String] key Indexer into raw SNS JSON message. @return [String] the value of the SNS’ field

# File lib/aws/sns/message.rb, line 67
def [] key
  @raw[key]
end
authentic?() click to toggle source

@return [Boolean] true when the {Message} is authentic:

SigningCert is hosted at amazonaws.com, on https
correctly cryptographically signed by sender
nothing went wrong during authenticating the {Message}

See docs.aws.amazon.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html

# File lib/aws/sns/message.rb, line 77
def authentic?
  begin
    decoded_from_base64 = decode signature
    public_key = get_public_key_from signing_cert_url
    public_key.verify OpenSSL::Digest::SHA1.new, decoded_from_base64, canonical_string
  rescue MessageWasNotAuthenticError
    false
  end
end
message() click to toggle source
# File lib/aws/sns/message.rb, line 112
def message
  @raw['Message']
end
message_id() click to toggle source
# File lib/aws/sns/message.rb, line 100
def message_id
  @raw['MessageId']
end
parse_from(json) click to toggle source
# File lib/aws/sns/message.rb, line 144
def parse_from json
  JSON.parse json
end
signature() click to toggle source
# File lib/aws/sns/message.rb, line 120
def signature
  @raw['Signature']
end
signature_version() click to toggle source
# File lib/aws/sns/message.rb, line 124
def signature_version
  @raw['SignatureVersion']
end
signing_cert_url() click to toggle source
# File lib/aws/sns/message.rb, line 128
def signing_cert_url
  @raw['SigningCertURL']
end
subject() click to toggle source
# File lib/aws/sns/message.rb, line 108
def subject
  @raw['Subject']
end
subscribe_url() click to toggle source
# File lib/aws/sns/message.rb, line 132
def subscribe_url
  @raw['SubscribeURL']
end
timestamp() click to toggle source
# File lib/aws/sns/message.rb, line 116
def timestamp
  @raw['Timestamp']
end
token() click to toggle source
# File lib/aws/sns/message.rb, line 136
def token
  @raw['Token']
end
topic_arn() click to toggle source
# File lib/aws/sns/message.rb, line 104
def topic_arn
  @raw['TopicArn']
end
type() click to toggle source

@return the message type

# File lib/aws/sns/message.rb, line 88
def type
  case when @raw['Type'] =~ /SubscriptionConfirmation/i
    then :SubscriptionConfirmation
  when @raw['Type'] =~ /Notification/i
    then :Notification
  when @raw['Type'] =~ /UnsubscribeConfirmation/i
    then :UnsubscribeConfirmation
  else
    :unknown
  end
end
unsubscribe_url() click to toggle source
# File lib/aws/sns/message.rb, line 140
def unsubscribe_url
  @raw['UnsubscribeURL']
end

Protected Instance Methods

canonical_string() click to toggle source
# File lib/aws/sns/message.rb, line 159
def canonical_string
  text = ''
  SIGNABLE_KEYS.each do |key|
    value = @raw[key]
    next if value.nil? or value.empty?
    text << key << "\n"
    text << value << "\n"
  end
  text
end
decode(raw) click to toggle source
# File lib/aws/sns/message.rb, line 149
def decode raw
  Base64.decode64 raw
end
download(url) click to toggle source
# File lib/aws/sns/message.rb, line 170
def download url
  uri = URI.parse(url)
  unless
    uri.scheme == 'https' &&
    uri.host.match(/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/) &&
    File.extname(uri.path) == '.pem'
  then
    msg = "cert is not hosted at AWS URL (https): #{url}"
    raise MessageWasNotAuthenticError, msg
  end
  tries = 0
  begin
    resp = https_get(url)
    resp.body
  rescue => error
    tries += 1
    retry if tries < 3
    raise error
  end
end
get_public_key_from(x509_pem_url) click to toggle source
# File lib/aws/sns/message.rb, line 153
def get_public_key_from(x509_pem_url)
  cert_pem = download x509_pem_url
  x509 = OpenSSL::X509::Certificate.new(cert_pem)
  OpenSSL::PKey::RSA.new(x509.public_key)
end
https_get(url) click to toggle source
# File lib/aws/sns/message.rb, line 191
def https_get(url)
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.start
  resp = http.request(Net::HTTP::Get.new(uri.request_uri))
  http.finish
  resp
end