kensa 1.2.0rc7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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