Class: Heroic::SNS::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/heroic/sns/message.rb

Overview

Encapsulates an SNS message. See: docs.aws.amazon.com/sns/latest/gsg/json-formats.html

Instance Method Summary collapse

Constructor Details

#initialize(json) ⇒ Message

Returns a new instance of Message.



24
25
26
27
28
# File 'lib/heroic/sns/message.rb', line 24

def initialize(json)
  @msg = ::JSON.parse(json)
rescue JSON::ParserError => e
  raise Error.new("failed to parse message as JSON: #{e.message}")
end

Instance Method Details

#==(other_message) ⇒ Object



83
84
85
# File 'lib/heroic/sns/message.rb', line 83

def ==(other_message)
  @msg == other_message.instance_variable_get(:@msg)
end

#bodyObject



65
66
67
# File 'lib/heroic/sns/message.rb', line 65

def body
  @msg['Message']
end

#hashObject



87
88
89
# File 'lib/heroic/sns/message.rb', line 87

def hash
  @msg.hash
end

#idObject



38
39
40
# File 'lib/heroic/sns/message.rb', line 38

def id
  @msg['MessageId']
end

#signatureObject

The message signature data, Base-64 decoded.



56
57
58
# File 'lib/heroic/sns/message.rb', line 56

def signature
  Base64::decode64(@msg['Signature'])
end

#signature_versionObject



47
48
49
# File 'lib/heroic/sns/message.rb', line 47

def signature_version
  @msg['SignatureVersion']
end

#signing_cert_urlObject



51
52
53
# File 'lib/heroic/sns/message.rb', line 51

def signing_cert_url
  @msg['SigningCertURL']
end

#subjectObject

The message may not have a subject.



61
62
63
# File 'lib/heroic/sns/message.rb', line 61

def subject
  @msg['Subject']
end

#subscribe_urlObject



69
70
71
# File 'lib/heroic/sns/message.rb', line 69

def subscribe_url
  @msg['SubscribeURL']
end

#timestampObject

The timestamp as a Time object.



43
44
45
# File 'lib/heroic/sns/message.rb', line 43

def timestamp
  Time.xmlschema(@msg['Timestamp'])
end

#to_jsonObject



99
100
101
# File 'lib/heroic/sns/message.rb', line 99

def to_json
  @msg.to_json
end

#to_sObject



91
92
93
94
95
96
97
# File 'lib/heroic/sns/message.rb', line 91

def to_s
  string = "<SNSMessage:\n"
  @msg.each do |k,v|
    string << sprintf("  %s: %s\n", k, v.inspect)
  end
  string << ">"
end

#tokenObject

The token is used to confirm subscriptions via the SNS API. If you visit the :subscribe_url, you can ignore this field.



79
80
81
# File 'lib/heroic/sns/message.rb', line 79

def token
  @msg['Token']
end

#topic_arnObject



34
35
36
# File 'lib/heroic/sns/message.rb', line 34

def topic_arn
  @msg['TopicArn']
end

#typeObject



30
31
32
# File 'lib/heroic/sns/message.rb', line 30

def type
  @msg['Type']
end

#unsubscribe_urlObject



73
74
75
# File 'lib/heroic/sns/message.rb', line 73

def unsubscribe_url
  @msg['UnsubscribeURL']
end

#verify!Object

Verifies the message signature. Raises an exception if it is not valid. See: docs.aws.amazon.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html

Raises:

  • (Errow)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/heroic/sns/message.rb', line 105

def verify!
  age = Time.now - timestamp
  raise Errow.new("timestamp is in the future", self) if age < 0
  raise Error.new("timestamp is too old", self) if age > MAXIMUM_ALLOWED_AGE
  if signature_version != '1'
    raise Error.new("unknown signature version: #{signature_version}", self)
  end
  if signing_cert_url !~ %r[^https://.*amazonaws\.com/]
    raise Error.new("signing certificate is not from amazonaws.com", self)
  end
  text = string_to_sign # will warn of invalid Type
  cert = CERTIFICATE_CACHE[signing_cert_url]
  digest = OpenSSL::Digest::SHA1.new
  unless cert.public_key.verify(digest, signature, text)
    raise Error.new("message signature is invalid", self)
  end
end