kensa 1.2.0rc7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ require 'test/helper'
2
+
3
+ class PlanChangeCheckTest < Test::Unit::TestCase
4
+ include Heroku::Kensa
5
+
6
+ %w{get post}.each do |method|
7
+ context "with sso #{method}" do
8
+ setup do
9
+ @data = Manifest.new(:method => method).skeleton.merge :id => 123, :plan => 'premium'
10
+ @data['api']['password'] = 'secret'
11
+ end
12
+
13
+ def check ; PlanChangeCheck ; end
14
+
15
+ test "working plan change call" do
16
+ use_provider_endpoint "working"
17
+ assert_valid
18
+ end
19
+
20
+ test "detects invalid status" do
21
+ use_provider_endpoint "invalid-status"
22
+ assert_invalid
23
+ end
24
+
25
+ test "detects missing auth" do
26
+ use_provider_endpoint "invalid-missing-auth"
27
+ assert_invalid
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ require 'test/helper'
2
+
3
+ class ProvisionCheckTest < Test::Unit::TestCase
4
+ include Heroku::Kensa
5
+
6
+ def check ; ProvisionCheck ; end
7
+
8
+ ['get', 'post'].each do |method|
9
+ context "with sso #{method}" do
10
+ setup do
11
+ @data = Manifest.new(:method => method).skeleton
12
+ @data['api']['password'] = 'secret'
13
+ end
14
+
15
+ test "trims url" do
16
+ c = check.new(@data)
17
+ assert_equal c.url, 'http://localhost:4567'
18
+ end
19
+
20
+ test "working provision call" do
21
+ use_provider_endpoint "working"
22
+ assert_valid
23
+ end
24
+
25
+ test "detects invalid JSON" do
26
+ use_provider_endpoint "invalid-json"
27
+ assert_invalid
28
+ end
29
+
30
+ test "detects invalid response" do
31
+ use_provider_endpoint "invalid-response"
32
+ assert_invalid
33
+ end
34
+
35
+ test "detects invalid status" do
36
+ use_provider_endpoint "invalid-status"
37
+ assert_invalid
38
+ end
39
+
40
+ test "detects missing id" do
41
+ use_provider_endpoint "invalid-missing-id"
42
+ assert_invalid
43
+ end
44
+
45
+ test "detects missing auth" do
46
+ use_provider_endpoint "invalid-missing-auth"
47
+ assert_invalid
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,81 @@
1
+ require 'test/helper'
2
+
3
+ class ProvisionResponseCheckTest < Test::Unit::TestCase
4
+ include Heroku::Kensa
5
+
6
+ def check ; ProvisionResponseCheck ; end
7
+
8
+ setup do
9
+ @response = { "id" => "123",
10
+ "config" => {
11
+ "MYADDON_URL" => "http://example.com/resource",
12
+ "MYADDON_CONFIG" => "value"
13
+ }}
14
+ @data = Manifest.new.skeleton.merge(:provision_response => @response)
15
+ @data['api']['config_vars'] << "MYADDON_CONFIG"
16
+ end
17
+
18
+ test "is valid if no errors" do
19
+ assert_valid
20
+ end
21
+
22
+ test "has an id" do
23
+ @response.delete("id")
24
+ assert_invalid
25
+ end
26
+
27
+ describe "when config is present" do
28
+
29
+ test "is a hash" do
30
+ @response["config"] = ""
31
+ assert_invalid
32
+ end
33
+
34
+ test "each key is previously set in the manifest" do
35
+ @response["config"]["MYSQL_URL"] = "http://..."
36
+ assert_invalid
37
+ end
38
+
39
+ test "each value is a string" do
40
+ @response["config"]["MYADDON_URL"] = {}
41
+ assert_invalid
42
+ end
43
+
44
+ test "asserts _URL vars are valid URIs" do
45
+ @response["config"]["MYADDON_URL"] = "abc:"
46
+ assert_invalid
47
+ end
48
+
49
+ test "asserts _URL vars have a host" do
50
+ @response["config"]["MYADDON_URL"] = "path"
51
+ assert_invalid
52
+ end
53
+
54
+ test "asserts _URL vars have a scheme" do
55
+ @response["config"]["MYADDON_URL"] = "//host/path"
56
+ assert_invalid
57
+ end
58
+
59
+ test "doesn't run URI test against other vars" do
60
+ @response["config"]['MYADDON_CONFIG'] = "abc:"
61
+ assert_valid
62
+ end
63
+
64
+ test "doesn't allow localhost URIs on production" do
65
+ @data[:env] = 'production'
66
+ @response["config"]["MYADDON_URL"] = "http://localhost/abc"
67
+ assert_invalid
68
+ end
69
+
70
+ test "asserts all vars in manifest are in response" do
71
+ @response["config"].delete('MYADDON_CONFIG')
72
+ assert_invalid
73
+ end
74
+
75
+ test "is valid otherwise" do
76
+ @response["config"]["MYADDON_URL"] = "http://localhost/abc"
77
+ assert_valid
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1 @@
1
+ exit(1) if ARGV.first == 'fail'
@@ -0,0 +1,227 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'json'
4
+
5
+ enable :sessions
6
+
7
+ helpers do
8
+ def heroku_only!
9
+ unless auth_heroku?
10
+ response['WWW-Authenticate'] = %(Basic realm="Kensa Test Server")
11
+ unauthorized!(401)
12
+ end
13
+ end
14
+
15
+ def auth_heroku?
16
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
17
+ @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['myaddon', 'secret']
18
+ end
19
+
20
+ def unauthorized!(status=403)
21
+ throw(:halt, [status, "Not authorized\n"])
22
+ end
23
+
24
+ def make_token
25
+ Digest::SHA1.hexdigest([params[:id], 'SSO_SALT', params[:timestamp]].join(':'))
26
+ end
27
+
28
+ def json_must_include(keys)
29
+ params = JSON.parse(request.body.read)
30
+ keys.each do |param|
31
+ raise "#{param} not included with request" unless params.keys.include? param
32
+ end
33
+ end
34
+
35
+ def login(heroku_user=true)
36
+ session.clear
37
+ session[:logged_in] = true
38
+ session[:heroku] = heroku_user
39
+ redirect '/'
40
+ end
41
+ end
42
+
43
+ post '/heroku/resources' do
44
+ heroku_only!
45
+ { :id => 123 }.to_json
46
+ end
47
+
48
+ post '/working/heroku/resources' do
49
+ json_must_include(%w{heroku_id plan callback_url logplex_token options})
50
+ heroku_only!
51
+ { :id => 123 }.to_json
52
+ end
53
+
54
+ post '/cmd-line-options/heroku/resources' do
55
+ heroku_only!
56
+ { :id => 123 }.to_json
57
+ end
58
+
59
+ post '/invalid-json/heroku/resources' do
60
+ heroku_only!
61
+ 'invalidjson'
62
+ end
63
+
64
+ post '/invalid-response/heroku/resources' do
65
+ heroku_only!
66
+ nil.to_json
67
+ end
68
+
69
+ post '/invalid-status/heroku/resources' do
70
+ heroku_only!
71
+ status 422
72
+ { :id => 123 }.to_json
73
+ end
74
+
75
+ post '/invalid-missing-id/heroku/resources' do
76
+ heroku_only!
77
+ { :noid => 123 }.to_json
78
+ end
79
+
80
+ post '/invalid-missing-auth/heroku/resources' do
81
+ { :id => 123 }.to_json
82
+ end
83
+
84
+
85
+ put '/working/heroku/resources/:id' do
86
+ json_must_include(%w{heroku_id plan})
87
+ heroku_only!
88
+ {}.to_json
89
+ end
90
+
91
+ put '/invalid-missing-auth/heroku/resources/:id' do
92
+ { :id => 123 }.to_json
93
+ end
94
+
95
+ put '/invalid-status/heroku/resources/:id' do
96
+ heroku_only!
97
+ status 422
98
+ {}.to_json
99
+ end
100
+
101
+
102
+ delete '/working/heroku/resources/:id' do
103
+ heroku_only!
104
+ "Ok"
105
+ end
106
+
107
+ def sso
108
+ unauthorized! unless params[:id] && params[:token]
109
+ unauthorized! unless params[:timestamp].to_i > (Time.now-60*2).to_i
110
+ unauthorized! unless params[:token] == make_token
111
+ response.set_cookie('heroku-nav-data', params['nav-data'])
112
+ login
113
+ end
114
+
115
+ get '/working/heroku/resources/:id' do
116
+ sso
117
+ end
118
+
119
+ post '/working/sso/login' do
120
+ puts params.inspect
121
+ sso
122
+ end
123
+
124
+ def notoken
125
+ unauthorized! unless params[:id] && params[:token]
126
+ unauthorized! unless params[:timestamp].to_i > (Time.now-60*2).to_i
127
+ response.set_cookie('heroku-nav-data', params['nav-data'])
128
+ login
129
+ end
130
+
131
+ get '/notoken/heroku/resources/:id' do
132
+ notoken
133
+ end
134
+
135
+ post '/notoken/sso/login' do
136
+ notoken
137
+ end
138
+
139
+ def notimestamp
140
+ unauthorized! unless params[:id] && params[:token]
141
+ unauthorized! unless params[:token] == make_token
142
+ response.set_cookie('heroku-nav-data', params['nav-data'])
143
+ login
144
+ end
145
+
146
+ get '/notimestamp/heroku/resources/:id' do
147
+ notimestamp
148
+ end
149
+
150
+ post '/notimestamp/sso/login' do
151
+ notimestamp
152
+ end
153
+
154
+ def nolayout
155
+ unauthorized! unless params[:id] && params[:token]
156
+ unauthorized! unless params[:timestamp].to_i > (Time.now-60*2).to_i
157
+ unauthorized! unless params[:token] == make_token
158
+ response.set_cookie('heroku-nav-data', params['nav-data'])
159
+ login(false)
160
+ end
161
+
162
+ get '/nolayout/heroku/resources/:id' do
163
+ nolayout
164
+ end
165
+
166
+ post '/nolayout/sso/login' do
167
+ nolayout
168
+ end
169
+
170
+ def nocookie
171
+ unauthorized! unless params[:id] && params[:token]
172
+ unauthorized! unless params[:timestamp].to_i > (Time.now-60*2).to_i
173
+ unauthorized! unless params[:token] == make_token
174
+ login
175
+ end
176
+
177
+ get '/nocookie/heroku/resources/:id' do
178
+ nocookie
179
+ end
180
+
181
+ post '/nocookie/sso/login' do
182
+ nocookie
183
+ end
184
+
185
+ def badcookie
186
+ unauthorized! unless params[:id] && params[:token]
187
+ unauthorized! unless params[:timestamp].to_i > (Time.now-60*2).to_i
188
+ unauthorized! unless params[:token] == make_token
189
+ response.set_cookie('heroku-nav-data', 'wrong value')
190
+ login
191
+ end
192
+
193
+ get '/badcookie/heroku/resources/:id' do
194
+ badcookie
195
+ end
196
+
197
+ post '/badcookie/sso/login' do
198
+ badcookie
199
+ end
200
+
201
+ def sso_user
202
+ head 404 unless params[:email] == 'username@example.com'
203
+ sso
204
+ end
205
+
206
+ get '/user/heroku/resources/:id' do
207
+ sso_user
208
+ end
209
+
210
+ post '/user/sso/login' do
211
+ sso_user
212
+ end
213
+
214
+ get '/' do
215
+ unauthorized! unless session[:logged_in]
216
+ haml :index
217
+ end
218
+
219
+ __END__
220
+
221
+ @@ index
222
+ %html
223
+ %body
224
+ - if session[:heroku]
225
+ #heroku-header
226
+ %h1 Heroku
227
+ %h1 Sample Addon
@@ -0,0 +1,58 @@
1
+ require 'test/helper'
2
+
3
+ class SsoCheckTest < Test::Unit::TestCase
4
+ include Heroku::Kensa
5
+
6
+
7
+ def check ; SsoCheck ; end
8
+ %w{get post}.each do |method|
9
+ context "via #{method}" do
10
+ setup do
11
+ @data = Manifest.new(:sso => true, :method => method).
12
+ skeleton.merge :id => 123
13
+ @data['api']['sso_salt'] = 'SSO_SALT'
14
+ end
15
+
16
+ test "working sso request" do
17
+ use_provider_endpoint('working', 'sso')
18
+ assert_valid
19
+ end
20
+
21
+ test "rejects bad token" do
22
+ use_provider_endpoint("notoken", 'sso')
23
+ assert_invalid
24
+ end
25
+
26
+ test "rejects old timestamp" do
27
+ use_provider_endpoint("notimestamp", 'sso')
28
+ assert_invalid
29
+ end
30
+
31
+ test "reject omitted sso salt" do
32
+ @data['api'].delete 'sso_salt'
33
+ use_provider_endpoint("working", 'sso')
34
+ assert_invalid
35
+ end
36
+
37
+ test "reject missing heroku layout" do
38
+ use_provider_endpoint("nolayout", 'sso')
39
+ assert_invalid
40
+ end
41
+
42
+ test "reject missing cookie" do
43
+ use_provider_endpoint("nocookie", 'sso')
44
+ assert_invalid
45
+ end
46
+
47
+ test "reject invalid cookie value" do
48
+ use_provider_endpoint("badcookie", 'sso')
49
+ assert_invalid
50
+ end
51
+
52
+ test "sends email param" do
53
+ use_provider_endpoint("user", 'sso')
54
+ assert_valid
55
+ end
56
+ end
57
+ end
58
+ end