sns_endpoint 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sns_endpoint.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Piotr Szmielew
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ # SnsEndpoint
2
+
3
+ Simple gem containing Sinatra engine, designed to help you utilize SNS http post service.
4
+ Use inside Rails (as an engine) or outside - as a standalone application.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'sns_endpoint'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install sns_endpoint
19
+
20
+ ## Usage
21
+
22
+ Configure using SnsEndpoint.setup, providing block, like this:
23
+ ```ruby
24
+ SnsEndpoint.setup do |config|
25
+ config.topics_list = ['first_topic', 'second_topic'] #list of topics that endpoint should respond to subscription request
26
+ config.subscribe_proc = Proc.new { |message| p message } #proc that should be executed when subscribe request got received and responded to, passed argument is message (json object)
27
+ config.message_proc = Proc.new { |message| p message } #proc that should be executed when message got send to endpoint
28
+ end
29
+ ```
30
+
31
+ for example in Rails initializer.
32
+
33
+ Use as Rails engine:
34
+
35
+ * mount in routes.rb:
36
+ ```ruby
37
+ mount SnsEndpoint::Core => "/sns_endpoint"
38
+ ```
39
+
40
+ Use as a standalone app:
41
+ Example script:
42
+ ```ruby
43
+ require 'rubygems'
44
+ require 'sns_endpoint'
45
+ SnsEndpoint.setup do |config|
46
+ config.topics_list = ['first_topic', 'second_topic'] #list of topics that endpoint should respond to subscription request
47
+ config.subscribe_proc = Proc.new { |message| p message } #proc that should be executed when subscribe request got received and responded to, passed argument is message (json object)
48
+ config.message_proc = Proc.new { |message| p message } #proc that should be executed when message got send to endpoint
49
+ end
50
+ SnsEndpoint::Core.run!
51
+ ```
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,159 @@
1
+ # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+
15
+ #modyfied version of message.rb from Aws-sdk fork by petemounce
16
+
17
+ require 'base64'
18
+ require 'json'
19
+ require 'openssl'
20
+ require 'httparty'
21
+
22
+ module SnsEndpoint
23
+ module AWS
24
+ class SNS
25
+ class MessageWasNotAuthenticError < StandardError
26
+ end
27
+ class Message
28
+ attr_accessor :origin, :raw
29
+
30
+ def initialize sns
31
+ if sns.is_a? String
32
+ @raw = parse_from sns
33
+ else
34
+ @raw = sns
35
+ end
36
+ @origin = :sns
37
+ end
38
+
39
+ def [] key
40
+ @raw[key]
41
+ end
42
+
43
+ def authentic?
44
+ begin
45
+ decoded_from_base64 = decode signature
46
+ public_key = get_public_key_from signing_cert_url
47
+ public_key.verify OpenSSL::Digest::SHA1.new, decoded_from_base64, canonical_string
48
+ rescue MessageWasNotAuthenticError
49
+ false
50
+ end
51
+ end
52
+
53
+ def type
54
+ case when @raw['Type'] =~ /SubscriptionConfirmation/i
55
+ then :SubscriptionConfirmation
56
+ when @raw['Type'] =~ /Notification/i
57
+ then :Notification
58
+ when @raw['Type'] =~ /UnsubscribeConfirmation/i
59
+ then :UnsubscribeConfirmation
60
+ else
61
+ :unknown
62
+ end
63
+ end
64
+
65
+ def message_id
66
+ @raw['MessageId']
67
+ end
68
+
69
+ def topic_arn
70
+ @raw['TopicArn']
71
+ end
72
+
73
+ def subject
74
+ @raw['Subject']
75
+ end
76
+
77
+ def message
78
+ @raw['Message']
79
+ end
80
+
81
+ def timestamp
82
+ @raw['Timestamp']
83
+ end
84
+
85
+ def signature
86
+ @raw['Signature']
87
+ end
88
+
89
+ def signature_version
90
+ @raw['SignatureVersion']
91
+ end
92
+
93
+ def signing_cert_url
94
+ @raw['SigningCertURL']
95
+ end
96
+
97
+ def unsubscribe_url
98
+ @raw['UnsubscribeURL']
99
+ end
100
+
101
+ def subscribe_url
102
+ @raw['SubscribeURL']
103
+ end
104
+
105
+ def token
106
+ @raw['Token']
107
+ end
108
+
109
+ def parse_from json
110
+ JSON.parse json
111
+ end
112
+
113
+ protected
114
+ def decode raw
115
+ Base64.decode64 raw
116
+ end
117
+
118
+ def get_public_key_from(x509_pem_url)
119
+ cert_pem = download x509_pem_url
120
+ x509 = OpenSSL::X509::Certificate.new(cert_pem)
121
+ OpenSSL::PKey::RSA.new(x509.public_key)
122
+ end
123
+
124
+ def canonical_string
125
+ if type == :SubscriptionConfirmation
126
+ text = "Message\n#{message}\n"
127
+ text += "MessageId\n#{message_id}\n"
128
+ text += "SubscribeURL\n#{subscribe_url}\n"
129
+ text += "Timestamp\n#{timestamp}\n"
130
+ text += "Token\n#{token}\n"
131
+ text += "TopicArn\n#{topic_arn}\n"
132
+ text += "Type\n#{type}\n"
133
+ else
134
+ text = "Message\n#{message}\n"
135
+ text += "MessageId\n#{message_id}\n"
136
+ text += "Subject\n#{subject}\n" unless subject.nil? or subject.empty?
137
+ text += "Timestamp\n#{timestamp}\n"
138
+ text += "TopicArn\n#{topic_arn}\n"
139
+ text += "Type\n#{type}\n"
140
+ end
141
+ text
142
+ end
143
+
144
+ def download url
145
+ raise MessageWasNotAuthenticError, "cert is not hosted at AWS URL (https): #{url}" unless url =~ /^https.*amazonaws\.com\/.*$/i
146
+ tries = 0
147
+ begin
148
+ response = HTTParty.get url
149
+ response.body
150
+ rescue => msg
151
+ tries += 1
152
+ retry if tries <= 3
153
+ raise StandardError, "SNS signing cert could not be retrieved after #{tries} tries.\n#{msg}"
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,36 @@
1
+ require "rubygems"
2
+ require 'bundler/setup'
3
+ require "sns_endpoint/version"
4
+ require 'sinatra'
5
+ require 'json'
6
+ require 'message'
7
+
8
+ module SnsEndpoint
9
+
10
+ class << self
11
+ attr_accessor :topics_list, :subscribe_proc, :message_proc
12
+ end
13
+
14
+ def self.setup(&block)
15
+ yield self
16
+ end
17
+
18
+ class Core < Sinatra::Base
19
+
20
+ post '/' do
21
+ json = JSON.parse(request.body.read)
22
+ sns = SnsEndpoint::AWS::SNS::Message.new json
23
+ if sns.authentic?
24
+ if sns.type == :SubscriptionConfirmation
25
+ if SnsEndpoint.topics_list.include? json['TopicArn']
26
+ HTTParty.get json['SubscribeURL']
27
+ SnsEndpoint.subscribe_proc.call(json)
28
+ end
29
+ elsif sns.type == :Notification
30
+ SnsEndpoint.message_proc.call(json)
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module SnsEndpoint
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/sns_endpoint/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Piotr Szmielew"]
6
+ gem.email = ["p.szmielew@ava.waw.pl"]
7
+ gem.description = %q{Gem containing sinatra engine to utilize SNS notifications.}
8
+ gem.summary = %q{Gem containing sinatra engine to utilize SNS notifications.}
9
+ gem.homepage = "http://github.com/elibri/sns_endpoint"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "sns_endpoint"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = SnsEndpoint::VERSION
17
+
18
+
19
+ gem.add_runtime_dependency "httparty"
20
+ gem.add_runtime_dependency "sinatra"
21
+ gem.add_runtime_dependency "json"
22
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sns_endpoint
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Piotr Szmielew
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-06-24 00:00:00 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: httparty
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: sinatra
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: json
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ description: Gem containing sinatra engine to utilize SNS notifications.
62
+ email:
63
+ - p.szmielew@ava.waw.pl
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - .gitignore
72
+ - Gemfile
73
+ - LICENSE
74
+ - README.md
75
+ - Rakefile
76
+ - lib/message.rb
77
+ - lib/sns_endpoint.rb
78
+ - lib/sns_endpoint/version.rb
79
+ - sns_endpoint.gemspec
80
+ homepage: http://github.com/elibri/sns_endpoint
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.21
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Gem containing sinatra engine to utilize SNS notifications.
113
+ test_files: []
114
+