maestrano 0.11.0 → 0.12.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +17 -8
- data/LICENSE +1 -1
- data/README.md +91 -14
- data/lib/maestrano/account/bill.rb +1 -1
- data/lib/maestrano/account/recurring_bill.rb +1 -1
- data/lib/maestrano/api/object.rb +1 -0
- data/lib/maestrano/api/operation/base.rb +13 -15
- data/lib/maestrano/api/operation/create.rb +1 -1
- data/lib/maestrano/api/operation/delete.rb +1 -1
- data/lib/maestrano/api/operation/list.rb +1 -1
- data/lib/maestrano/api/operation/update.rb +1 -1
- data/lib/maestrano/connec/client.rb +6 -5
- data/lib/maestrano/preset.rb +23 -0
- data/lib/maestrano/saml/request.rb +4 -3
- data/lib/maestrano/saml/response.rb +3 -2
- data/lib/maestrano/sso/base_user.rb +3 -2
- data/lib/maestrano/sso/session.rb +3 -2
- data/lib/maestrano/sso.rb +18 -17
- data/lib/maestrano/version.rb +1 -1
- data/lib/maestrano.rb +59 -8
- data/test/maestrano/account/bill_test.rb +54 -13
- data/test/maestrano/account/user_test.rb +20 -0
- data/test/maestrano/connec/client_test.rb +210 -66
- data/test/maestrano/maestrano_test.rb +141 -4
- data/test/maestrano/saml/response_test.rb +83 -0
- data/test/maestrano/sso/session_test.rb +61 -0
- data/test/maestrano/sso_test.rb +246 -85
- metadata +4 -3
@@ -8,6 +8,8 @@ class MaestranoTest < Test::Unit::TestCase
|
|
8
8
|
|
9
9
|
'api.id' => 'app-f54ds4f8',
|
10
10
|
'api.key' => 'someapikey',
|
11
|
+
|
12
|
+
'connec.enabled' => true,
|
11
13
|
|
12
14
|
'sso.enabled' => false,
|
13
15
|
'sso.slo_enabled' => false,
|
@@ -28,6 +30,8 @@ class MaestranoTest < Test::Unit::TestCase
|
|
28
30
|
|
29
31
|
config.api.id = @config['api.id']
|
30
32
|
config.api.key = @config['api.key']
|
33
|
+
|
34
|
+
config.connec.enabled = @config['connec.enabled']
|
31
35
|
|
32
36
|
config.sso.enabled = @config['sso.enabled']
|
33
37
|
config.sso.slo_enabled = @config['sso.slo_enabled']
|
@@ -52,7 +56,7 @@ class MaestranoTest < Test::Unit::TestCase
|
|
52
56
|
end
|
53
57
|
|
54
58
|
should "set the sso.creation_mode to 'real' by default" do
|
55
|
-
Maestrano.
|
59
|
+
Maestrano.configs = {'default' => Maestrano::Configuration.new }
|
56
60
|
Maestrano.configure { |config| config.app.host = "https://someapp.com" }
|
57
61
|
assert_equal 'real', Maestrano.param('sso.creation_mode')
|
58
62
|
end
|
@@ -63,7 +67,7 @@ class MaestranoTest < Test::Unit::TestCase
|
|
63
67
|
end
|
64
68
|
|
65
69
|
should "assign the sso.idm to app.host if not provided" do
|
66
|
-
Maestrano.
|
70
|
+
Maestrano.configs = {'default' => Maestrano::Configuration.new }
|
67
71
|
Maestrano.configure { |config| config.app.host = "https://someapp.com" }
|
68
72
|
assert_equal Maestrano.param('app.host'), Maestrano.param('sso.idm')
|
69
73
|
end
|
@@ -92,7 +96,7 @@ class MaestranoTest < Test::Unit::TestCase
|
|
92
96
|
should "return the right test parameters" do
|
93
97
|
Maestrano.configure { |config| config.environment = 'test' }
|
94
98
|
|
95
|
-
['api.host','api.base','sso.idp', 'sso.name_id_format', 'sso.x509_certificate', 'connec.host','connec.base_path'].each do |parameter|
|
99
|
+
['api.host', 'api.base', 'sso.idp', 'sso.name_id_format', 'sso.x509_certificate', 'connec.host', 'connec.base_path'].each do |parameter|
|
96
100
|
assert_equal Maestrano::Configuration::EVT_CONFIG['test'][parameter], Maestrano.param(parameter)
|
97
101
|
end
|
98
102
|
end
|
@@ -100,13 +104,146 @@ class MaestranoTest < Test::Unit::TestCase
|
|
100
104
|
should "return the right production parameters" do
|
101
105
|
Maestrano.configure { |config| config.environment = 'production' }
|
102
106
|
|
103
|
-
['api.host','api.base','sso.idp', 'sso.name_id_format', 'sso.x509_certificate','connec.host','connec.base_path'].each do |parameter|
|
107
|
+
['api.host', 'api.base', 'sso.idp', 'sso.name_id_format', 'sso.x509_certificate', 'connec.host', 'connec.base_path'].each do |parameter|
|
104
108
|
assert_equal Maestrano::Configuration::EVT_CONFIG['production'][parameter], Maestrano.param(parameter)
|
105
109
|
end
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
113
|
+
|
114
|
+
context "new style configuration with presets" do
|
115
|
+
setup do
|
116
|
+
@preset = 'mypreset'
|
117
|
+
|
118
|
+
@config = {
|
119
|
+
'environment' => 'production',
|
120
|
+
'app.host' => 'http://mysuperapp.com',
|
121
|
+
|
122
|
+
'api.id' => 'app-f54ds4f8',
|
123
|
+
'api.key' => 'someapikey',
|
124
|
+
|
125
|
+
'connec.enabled' => true,
|
126
|
+
|
127
|
+
'sso.enabled' => false,
|
128
|
+
'sso.slo_enabled' => false,
|
129
|
+
'sso.init_path' => '/mno/sso/init',
|
130
|
+
'sso.consume_path' => '/mno/sso/consume',
|
131
|
+
'sso.creation_mode' => 'real',
|
132
|
+
'sso.idm' => 'http://idp.mysuperapp.com',
|
133
|
+
|
134
|
+
'webhook.account.groups_path' => '/mno/groups/:id',
|
135
|
+
'webhook.account.group_users_path' => '/mno/groups/:group_id/users/:id',
|
136
|
+
'webhook.connec.notifications_path' => 'mno/receive',
|
137
|
+
'webhook.connec.subscriptions' => { organizations: true, people: true }
|
138
|
+
}
|
139
|
+
|
140
|
+
@preset_config = {
|
141
|
+
'environment' => 'production',
|
142
|
+
'app.host' => 'http://myotherapp.com',
|
143
|
+
|
144
|
+
'api.id' => 'app-553941',
|
145
|
+
'api.key' => 'otherapikey',
|
146
|
+
}
|
147
|
+
|
148
|
+
Maestrano.configure do |config|
|
149
|
+
config.environment = @config['environment']
|
150
|
+
config.app.host = @config['app.host']
|
151
|
+
|
152
|
+
config.api.id = @config['api.id']
|
153
|
+
config.api.key = @config['api.key']
|
154
|
+
|
155
|
+
config.connec.enabled = @config['connec.enabled']
|
156
|
+
|
157
|
+
config.sso.enabled = @config['sso.enabled']
|
158
|
+
config.sso.slo_enabled = @config['sso.slo_enabled']
|
159
|
+
config.sso.idm = @config['sso.idm']
|
160
|
+
config.sso.init_path = @config['sso.init_path']
|
161
|
+
config.sso.consume_path = @config['sso.consume_path']
|
162
|
+
config.sso.creation_mode = @config['sso.creation_mode']
|
163
|
+
|
164
|
+
config.webhook.account.groups_path = @config['webhook.account.groups_path']
|
165
|
+
config.webhook.account.group_users_path = @config['webhook.account.group_users_path']
|
166
|
+
|
167
|
+
config.webhook.connec.notifications_path = @config['webhook.connec.notifications_path']
|
168
|
+
config.webhook.connec.subscriptions = @config['webhook.connec.subscriptions']
|
169
|
+
end
|
170
|
+
|
171
|
+
Maestrano[@preset].configure do |config|
|
172
|
+
config.environment = @preset_config['environment']
|
173
|
+
config.app.host = @preset_config['app.host']
|
174
|
+
|
175
|
+
config.api.id = @preset_config['api.id']
|
176
|
+
config.api.key = @preset_config['api.key']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
should "return the specified parameters" do
|
181
|
+
@preset_config.keys.each do |key|
|
182
|
+
assert_equal @preset_config[key], Maestrano[@preset].param(key)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
should "set the sso.creation_mode to 'real' by default" do
|
187
|
+
Maestrano.configs = {@preset => Maestrano::Configuration.new }
|
188
|
+
Maestrano[@preset].configure { |config| config.app.host = "https://someapp.com" }
|
189
|
+
assert_equal 'real', Maestrano[@preset].param('sso.creation_mode')
|
190
|
+
end
|
191
|
+
|
192
|
+
should "build the api_token based on the app_id and api_key" do
|
193
|
+
Maestrano[@preset].configure { |config| config.app_id = "bla"; config.api_key = "blo" }
|
194
|
+
assert_equal "bla:blo", Maestrano[@preset].param('api.token')
|
195
|
+
end
|
109
196
|
|
197
|
+
should "assign the sso.idm to app.host if not provided" do
|
198
|
+
Maestrano.configs = {@preset => Maestrano::Configuration.new }
|
199
|
+
Maestrano[@preset].configure { |config| config.app.host = "https://someapp.com" }
|
200
|
+
assert_equal Maestrano[@preset].param('app.host'), Maestrano[@preset].param('sso.idm')
|
201
|
+
end
|
202
|
+
|
203
|
+
should "force assign the api.lang" do
|
204
|
+
Maestrano[@preset].configure { |config| config.api.lang = "bla" }
|
205
|
+
assert_equal 'ruby', Maestrano[@preset].param('api.lang')
|
206
|
+
end
|
207
|
+
|
208
|
+
should "force assign the api.lang_version" do
|
209
|
+
Maestrano[@preset].configure { |config| config.api.lang_version = "123456" }
|
210
|
+
assert_equal "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})", Maestrano[@preset].param('api.lang_version')
|
211
|
+
end
|
212
|
+
|
213
|
+
should "force assign the api.version" do
|
214
|
+
Maestrano[@preset].configure { |config| config.api.version = "1245" }
|
215
|
+
assert_equal Maestrano::VERSION, Maestrano[@preset].param('api.version')
|
216
|
+
end
|
217
|
+
|
218
|
+
should "force slo_enabled to false if sso is disabled" do
|
219
|
+
Maestrano[@preset].configure { |config| config.sso.slo_enabled = true; config.sso.enabled = false }
|
220
|
+
assert_false Maestrano[@preset].param('sso.slo_enabled')
|
221
|
+
end
|
222
|
+
|
223
|
+
should "allow overwritting connec configuration" do
|
224
|
+
Maestrano[@preset].configure { |config| config.connec.host = 'http://mydataserver.org'; config.connec.base_path = '/data' }
|
225
|
+
assert_equal 'http://mydataserver.org', Maestrano[@preset].param('connec.host')
|
226
|
+
assert_equal '/data', Maestrano[@preset].param('connec.base_path')
|
227
|
+
end
|
228
|
+
|
229
|
+
context "with environment params" do
|
230
|
+
should "return the right test parameters" do
|
231
|
+
Maestrano[@preset].configure { |config| config.environment = 'test' }
|
232
|
+
|
233
|
+
['api.host','api.base','sso.idp', 'sso.name_id_format', 'sso.x509_certificate', 'connec.host','connec.base_path'].each do |parameter|
|
234
|
+
assert_equal Maestrano::Configuration::EVT_CONFIG['test'][parameter], Maestrano[@preset].param(parameter)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
should "return the right production parameters" do
|
239
|
+
Maestrano[@preset].configure { |config| config.environment = 'production' }
|
240
|
+
|
241
|
+
['api.host','api.base','sso.idp', 'sso.name_id_format', 'sso.x509_certificate','connec.host','connec.base_path'].each do |parameter|
|
242
|
+
assert_equal Maestrano::Configuration::EVT_CONFIG['production'][parameter], Maestrano[@preset].param(parameter)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
110
247
|
|
111
248
|
context "old style configuration" do
|
112
249
|
setup do
|
@@ -156,6 +156,89 @@ module Maestrano
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
+
context 'with presets' do
|
160
|
+
context "#is_valid?" do
|
161
|
+
setup do
|
162
|
+
@preset = 'mypreset'
|
163
|
+
|
164
|
+
@config = {
|
165
|
+
'environment' => 'production',
|
166
|
+
'app.host' => 'http://mysuperapp.com',
|
167
|
+
|
168
|
+
'sso.enabled' => false,
|
169
|
+
'sso.slo_enabled' => false,
|
170
|
+
'sso.init_path' => '/mno/sso/init',
|
171
|
+
'sso.consume_path' => '/mno/sso/consume',
|
172
|
+
'sso.creation_mode' => 'real',
|
173
|
+
'sso.idm' => 'http://idp.mysuperapp.com'
|
174
|
+
}
|
175
|
+
|
176
|
+
@preset_config = {
|
177
|
+
'environment' => 'production',
|
178
|
+
'app.host' => 'http://myotherapp.com',
|
179
|
+
|
180
|
+
'sso.enabled' => false,
|
181
|
+
'sso.slo_enabled' => false,
|
182
|
+
'sso.init_path' => '/mno/sso/init',
|
183
|
+
'sso.consume_path' => '/mno/sso/consume',
|
184
|
+
'sso.creation_mode' => 'real',
|
185
|
+
'sso.idm' => 'http://idp.myotherapp.com',
|
186
|
+
'sso.x509_fingerprint' => signature_fingerprint_1
|
187
|
+
}
|
188
|
+
|
189
|
+
Maestrano.configure do |config|
|
190
|
+
config.environment = @config['environment']
|
191
|
+
config.app.host = @config['app.host']
|
192
|
+
|
193
|
+
config.sso.enabled = @config['sso.enabled']
|
194
|
+
config.sso.slo_enabled = @config['sso.slo_enabled']
|
195
|
+
config.sso.idm = @config['sso.idm']
|
196
|
+
config.sso.init_path = @config['sso.init_path']
|
197
|
+
config.sso.consume_path = @config['sso.consume_path']
|
198
|
+
config.sso.creation_mode = @config['sso.creation_mode']
|
199
|
+
end
|
200
|
+
|
201
|
+
Maestrano[@preset].configure do |config|
|
202
|
+
config.environment = @preset_config['environment']
|
203
|
+
config.app.host = @preset_config['app.host']
|
204
|
+
|
205
|
+
config.sso.enabled = @preset_config['sso.enabled']
|
206
|
+
config.sso.slo_enabled = @preset_config['sso.slo_enabled']
|
207
|
+
config.sso.idm = @preset_config['sso.idm']
|
208
|
+
config.sso.init_path = @preset_config['sso.init_path']
|
209
|
+
config.sso.consume_path = @preset_config['sso.consume_path']
|
210
|
+
config.sso.creation_mode = @preset_config['sso.creation_mode']
|
211
|
+
|
212
|
+
config.sso.x509_fingerprint = @preset_config['sso.x509_fingerprint']
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
should "return true when using certificate instead of fingerprint" do
|
217
|
+
response = Maestrano::Saml::Response[@preset].new(response_document_4)
|
218
|
+
response.stubs(:conditions).returns(nil)
|
219
|
+
assert response.is_valid?
|
220
|
+
end
|
221
|
+
|
222
|
+
should "not allow signature wrapping attack" do
|
223
|
+
response = Maestrano::Saml::Response[@preset].new(response_document_4)
|
224
|
+
response.stubs(:conditions).returns(nil)
|
225
|
+
assert response.is_valid?
|
226
|
+
assert response.name_id == "test@onelogin.com"
|
227
|
+
end
|
228
|
+
|
229
|
+
should "support dynamic namespace resolution on signature elements" do
|
230
|
+
Maestrano[@preset].configure do |config|
|
231
|
+
config.sso.x509_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA"
|
232
|
+
end
|
233
|
+
|
234
|
+
response = Maestrano::Saml::Response[@preset].new(fixture("no_signature_ns.xml"))
|
235
|
+
response.stubs(:conditions).returns(nil)
|
236
|
+
Maestrano::XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true)
|
237
|
+
assert response.validate!
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
159
242
|
context "#name_id" do
|
160
243
|
should "extract the value of the name id element" do
|
161
244
|
response = Maestrano::Saml::Response.new(response_document)
|
@@ -155,6 +155,67 @@ module Maestrano
|
|
155
155
|
assert_false @sso_session.valid?
|
156
156
|
end
|
157
157
|
end
|
158
|
+
|
159
|
+
context 'with preset' do
|
160
|
+
context "valid?" do
|
161
|
+
setup do
|
162
|
+
@preset = 'my-preset'
|
163
|
+
@sso_session = Maestrano::SSO::Session[@preset].new(@session)
|
164
|
+
Maestrano[@preset].configure { |c| c.sso.slo_enabled = true }
|
165
|
+
end
|
166
|
+
|
167
|
+
should "return true if Single Logout is disabled" do
|
168
|
+
Maestrano[@preset].configure { |c| c.sso.slo_enabled = false }
|
169
|
+
@sso_session.stubs(:remote_check_required?).returns(true)
|
170
|
+
@sso_session.stubs(:perform_remote_check).returns(false)
|
171
|
+
assert @sso_session.valid?
|
172
|
+
end
|
173
|
+
|
174
|
+
should "return true if_session is enabled and session is nil" do
|
175
|
+
sso_session = Maestrano::SSO::Session[@preset].new(nil)
|
176
|
+
assert sso_session.valid?(if_session: true)
|
177
|
+
end
|
178
|
+
|
179
|
+
should "return true if_session is enabled and session is empty" do
|
180
|
+
sso_session = Maestrano::SSO::Session[@preset].new({})
|
181
|
+
assert sso_session.valid?(if_session: true)
|
182
|
+
end
|
183
|
+
|
184
|
+
should "return true if no remote_check_required?" do
|
185
|
+
@sso_session.stubs(:remote_check_required?).returns(false)
|
186
|
+
assert @sso_session.valid?
|
187
|
+
assert @sso_session.valid?(if_session: true)
|
188
|
+
end
|
189
|
+
|
190
|
+
should "return true if remote_check_required? and valid" do
|
191
|
+
@sso_session.stubs(:remote_check_required?).returns(true)
|
192
|
+
@sso_session.stubs(:perform_remote_check).returns(true)
|
193
|
+
assert @sso_session.valid?
|
194
|
+
assert @sso_session.valid?(if_session: true)
|
195
|
+
end
|
196
|
+
|
197
|
+
should "update maestrano session with recheck timestamp if remote_check_required? and valid" do
|
198
|
+
recheck = (@sso_session.recheck + 600)
|
199
|
+
@sso_session.recheck = recheck
|
200
|
+
@sso_session.stubs(:remote_check_required?).returns(true)
|
201
|
+
@sso_session.stubs(:perform_remote_check).returns(true)
|
202
|
+
@sso_session.valid?
|
203
|
+
assert_equal JSON.parse(Base64.decode64(@session[:maestrano]))['session_recheck'], recheck.utc.iso8601
|
204
|
+
end
|
205
|
+
|
206
|
+
should "return false if remote_check_required? and invalid" do
|
207
|
+
@sso_session.stubs(:remote_check_required?).returns(true)
|
208
|
+
@sso_session.stubs(:perform_remote_check).returns(false)
|
209
|
+
assert_false @sso_session.valid?
|
210
|
+
assert_false @sso_session.valid?(if_session: true)
|
211
|
+
end
|
212
|
+
|
213
|
+
should "return false if internal session is nil" do
|
214
|
+
sso_session = Maestrano::SSO::Session[@preset].new(nil)
|
215
|
+
assert_false @sso_session.valid?
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
158
219
|
|
159
220
|
end
|
160
221
|
end
|