dot_net_services 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/LICENSE +21 -24
  2. data/README +26 -16
  3. data/Rakefile +65 -0
  4. data/lib/acs/saml_token_provider.rb +54 -0
  5. data/lib/acs/shared_secret_token_provider.rb +55 -0
  6. data/lib/acs/simple_api_auth_token_provider.rb +57 -0
  7. data/lib/acs/simple_web_token_provider.rb +54 -0
  8. data/lib/acs/token_constants.rb +112 -0
  9. data/lib/acs/token_info.rb +33 -0
  10. data/lib/acs/token_provider.rb +74 -0
  11. data/lib/acs/token_validator.rb +114 -0
  12. data/lib/common/dot_net_services_environment.rb +61 -0
  13. data/lib/common/environment.yml +23 -0
  14. data/lib/common/host_name_config.yml +45 -0
  15. data/lib/dot_net_services.rb +31 -144
  16. data/lib/service_bus/http_proxy.rb +34 -0
  17. data/lib/service_bus/locked_message_info.rb +34 -0
  18. data/lib/service_bus/message_buffer.rb +313 -0
  19. data/lib/service_bus/message_buffer_constants.rb +48 -0
  20. data/lib/service_bus/message_buffer_policy.rb +55 -0
  21. data/lib/service_bus/requests.rb +95 -0
  22. data/test/config/test_config.yml +40 -0
  23. data/test/dot_net_services_environment_test.rb +54 -0
  24. data/test/message_buffer_test.rb +96 -0
  25. data/test/token_test.rb +98 -0
  26. metadata +50 -48
  27. data/lib/dot_net_services/authentication.rb +0 -168
  28. data/lib/dot_net_services/error.rb +0 -4
  29. data/lib/dot_net_services/message_buffer.rb +0 -283
  30. data/lib/dot_net_services/session.rb +0 -308
  31. data/lib/net/http/create_mb.rb +0 -14
  32. data/lib/net/http/retrieve.rb +0 -14
  33. data/lib/net/http/subscribe.rb +0 -14
  34. data/lib/net/http/unsubscribe.rb +0 -14
  35. data/spec/integration/TestService/Service/AnonymousResourceService.cs +0 -9
  36. data/spec/integration/TestService/Service/App.config +0 -32
  37. data/spec/integration/TestService/Service/PlainTextService.cs +0 -37
  38. data/spec/integration/TestService/Service/Program.cs +0 -49
  39. data/spec/integration/TestService/Service/Properties/AssemblyInfo.cs +0 -33
  40. data/spec/integration/TestService/Service/ResourceContract.cs +0 -17
  41. data/spec/integration/TestService/Service/ResourceService.cs +0 -58
  42. data/spec/integration/TestService/Service/Service.csproj +0 -71
  43. data/spec/integration/TestService/TestService.sln +0 -33
  44. data/spec/integration/end_to_end_spec.rb +0 -84
  45. data/spec/integration/vmb_spec.rb +0 -30
  46. data/spec/spec_helper.rb +0 -23
  47. data/spec/unit/dot_net_services/authentication_spec.rb +0 -289
  48. data/spec/unit/dot_net_services/message_buffer_spec.rb +0 -161
  49. data/spec/unit/dot_net_services/session_spec.rb +0 -247
@@ -1,289 +0,0 @@
1
- require "#{File.dirname(__FILE__)}/../../spec_helper"
2
-
3
- module DotNetServices
4
-
5
- describe Authentication::UsernamePassword do
6
-
7
- describe "acting as a hash key" do
8
- before :each do
9
- @auth = Authentication::UsernamePassword.new('frodo', 'passw0rd')
10
- end
11
-
12
- it "should not be equal to an instance of another class" do
13
- different_class = stub('not the same class', :username => 'frodo', :password => 'passw0rd')
14
- different_class.should_receive(:is_a?).with(Authentication::UsernamePassword).and_return(false)
15
- @auth.should_not == different_class
16
- end
17
-
18
- it "should not be equal to an instance with different username or password" do
19
- @auth.should_not == Authentication::UsernamePassword.new('gandalf', 'passw0rd')
20
- @auth.should_not == Authentication::UsernamePassword.new('frodo', 'different passw0rd')
21
- end
22
-
23
- it "should equal to another instance with same username and password" do
24
- @auth.should == @auth
25
- @auth.should == Authentication::UsernamePassword.new('frodo', 'passw0rd')
26
- end
27
-
28
- it "should adequately identify an instance in a hash" do
29
- hash = {}
30
- hash[@auth] = :found
31
- hash[@auth].should == :found
32
-
33
- equivalent_auth = Authentication::UsernamePassword.new('frodo', 'passw0rd')
34
- hash[equivalent_auth].should == :found
35
-
36
- different_auth = Authentication::UsernamePassword.new('frodo', 'different passw0rd')
37
- hash[different_auth].should be_nil
38
- end
39
-
40
- end
41
-
42
- describe "authenticate()" do
43
-
44
- it "should obtain a token from DotNetServices STS" do
45
- http = mock_http
46
- response = mock('response')
47
- Time.stub!(:now).and_return(Time.at(0))
48
-
49
- http.should_receive(:get).with("/issuetoken.aspx?u=frodo&p=password").and_return(response)
50
- response.should_receive(:is_a?).with(Net::HTTPOK).and_return(true)
51
- response.stub!(:body).and_return('bWyFxQgby0gHyPWZ2LcIXnHgA1J5kALK4iM+QA==')
52
-
53
- auth = Authentication::UsernamePassword.new('frodo', 'password')
54
- auth.authenticate
55
- auth.token.value.should == 'bWyFxQgby0gHyPWZ2LcIXnHgA1J5kALK4iM+QA=='
56
- auth.token.expiry.should == Time.at(24 * 60 * 60)
57
- end
58
-
59
- it "should rewrite exception messages to avoid accidentally exposing username/password" do
60
- http = mock_http
61
- http.should_receive(:get).with("/issuetoken.aspx?u=frodo&p=password").and_raise("p=password")
62
- auth = Authentication::UsernamePassword.new('frodo', 'password')
63
-
64
- begin
65
- auth.authenticate
66
- rescue => e
67
- e.should be_instance_of(AuthenticationError)
68
- e.message.should_not =~ /password/
69
- end
70
- end
71
-
72
- it "should detect when the HTTP response code is wrong and blow up correctly" do
73
- http = mock_http
74
- not_found = stub("HTTPNotFound", :class => Net::HTTPNotFound)
75
- not_found.should_receive(:is_a?).with(Net::HTTPOK).and_return(false)
76
-
77
- http.should_receive(:get).with("/issuetoken.aspx?u=frodo&p=password").and_return(not_found)
78
- auth = Authentication::UsernamePassword.new('frodo', 'password')
79
-
80
- lambda { auth.authenticate }.should raise_error(AuthenticationError,
81
- "Failed to obtain a security token from the identity service. HTTP response was Net::HTTPNotFound")
82
- end
83
-
84
- # TODO Identity service response for this situation is not correct now. Implement test when they fix it
85
- it "should detect an invalid user/password situation and blow up correctly"
86
-
87
- # TODO asked MS what future-proof assertions can be made to see if it's a token
88
- it "should detect when response is not a token and blow up correctly"
89
- # do
90
- # http = mock_http
91
- # response = mock('response')
92
- # http.should_receive(:get).with("/issuetoken.aspx?u=frodo&p=password").and_return(response)
93
- # response.should_receive(:is_a?).with(Net::HTTPOK).and_return(true)
94
- # response.stub!(:body).and_return('NOT A TOKEN')
95
- #
96
- # auth = Authentication::UsernamePassword.new('frodo', 'password')
97
- # proc { auth.authenticate }.should raise_error(
98
- # AuthenticationError, "Response from identity service is not a valid token. " +
99
- # # TODO remove the line below when we are able to detect this situation explicitly
100
- # "This can indicate username/password mismatch.")
101
- # end
102
-
103
- it "should not acquire a new token if a token is already defined" do
104
- token = Authentication::Token.new("nh8hUpTSAeMW0RVkMRRaZtxJqfM==")
105
- auth = Authentication::UsernamePassword.new('frodo', 'password', token)
106
- Net::HTTP.should_not_receive(:new)
107
- auth.authenticate
108
- end
109
-
110
- it "should acquire new token if token is expired" do
111
- expired_token = Authentication::Token.new('expired/token==', Time.now - 1)
112
- new_token = Authentication::Token.new('new/token==', Time.now)
113
- auth = Authentication::UsernamePassword.new('frodo', 'password', expired_token)
114
-
115
- auth.should_receive(:acquire_token).and_return(new_token)
116
- request = {}
117
- auth.enhance(request)
118
- auth.token.should equal(new_token)
119
- request['X-MS-Identity-Token'].should == 'new/token=='
120
- end
121
-
122
- it "should acquire new token if token is not set" do
123
- auth = Authentication::UsernamePassword.new('frodo', 'password')
124
- auth.token.should be_nil
125
- new_token = Authentication::Token.new('new/token==', Time.now)
126
-
127
- auth.should_receive(:acquire_token).and_return(new_token)
128
-
129
- request = {}
130
- auth.enhance(request)
131
- auth.token.should equal(new_token)
132
- request['X-MS-Identity-Token'].should == 'new/token=='
133
- end
134
-
135
- def mock_http
136
- http = mock('http')
137
- Net::HTTP.should_receive(:new).with(DotNetServices.identity_host, 443).and_return(http)
138
- http.should_receive(:use_ssl=).with(true)
139
- http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
140
- http
141
- end
142
-
143
- end
144
-
145
- describe "enhance(request)" do
146
-
147
- it "should put a token into X-MS-Identity-Token header" do
148
- Time.stub!(:now).and_return(Time.at(0))
149
- request = {}
150
- token = Authentication::Token.new("a/token==", Time.at(1))
151
- auth = Authentication::UsernamePassword.new('frodo', 'password', token)
152
- auth.enhance(request)
153
- request['X-MS-Identity-Token'].should == "a/token=="
154
- end
155
-
156
- it "should acquire the token if necessary" do
157
- token = Authentication::Token.new("a/token==", Time.at(1))
158
- auth = Authentication::UsernamePassword.new('frodo', 'password')
159
- auth.should_receive(:acquire_token).and_return(token)
160
- request = {}
161
- auth.enhance(request)
162
- request['X-MS-Identity-Token'].should == "a/token=="
163
- end
164
-
165
- end
166
-
167
- end
168
-
169
- describe Authentication::Anonymous do
170
- describe "acting as a hash key" do
171
- it "should equal to any instance of the same class" do
172
- auth = Authentication::Anonymous.new
173
- auth.should == auth
174
- auth.should == Authentication::Anonymous.new
175
- auth.should_not == Object.new
176
- end
177
-
178
- it "should have a constant hash" do
179
- auth = Authentication::Anonymous.new
180
- auth.hash.should == -1
181
- end
182
- end
183
- end
184
-
185
- describe "setup(auth_data)" do
186
- it "should construct a user/password authentication handler given user and password" do
187
- authenticator = Authentication.setup(:username => 'me', :password => 'himom')
188
- authenticator.should be_instance_of(Authentication::UsernamePassword)
189
- end
190
-
191
- it "should construct an anonymous authentication handler given nothing" do
192
- authenticator = Authentication.setup(nil)
193
- authenticator.should be_instance_of(Authentication::Anonymous)
194
- end
195
-
196
- it "should construct an anonymous authentication handler given an empty hash" do
197
- authenticator = Authentication.setup({})
198
- authenticator.should be_instance_of(Authentication::Anonymous)
199
- end
200
-
201
- it "should construct a certificate authentication handler given certificate" do
202
- authenticator = Authentication.setup(:certificate => 'foo')
203
- authenticator.should be_instance_of(Authentication::Certificate)
204
- end
205
-
206
- it "should treat auth_data as auth handler if it's not a hash" do
207
- authenticator = Authentication.setup(:foo)
208
- authenticator.should == :foo
209
- end
210
-
211
- it "should blow up if username is given but password isn't, or vice versa" do
212
- proc {
213
- Authentication.setup(:username => 'foo')
214
- }.should raise_error(ArgumentError, "Auth data specifies username, but no password.")
215
-
216
- proc {
217
- authenticator = Authentication.setup(:password => 'foo')
218
- }.should raise_error(ArgumentError, "Auth data specifies password, but no username.")
219
- end
220
-
221
- it "should blow up if both username/password and certificate are in auth_data hash" do
222
- proc {
223
- authenticator = Authentication.setup(:username => 'foo', :password => 'bar', :certificate => 'baz')
224
- }.should raise_error(ArgumentError, "Cannot determine authentication type from auth data.")
225
- end
226
-
227
- it "should blow up if given unknown options in auth data" do
228
- proc {
229
- authenticator = Authentication.setup(:username => 'foo', :password => 'bar', :something => true, :something_else => true)
230
- }.should raise_error(ArgumentError, /^Auth data contains unknown options:/)
231
- end
232
-
233
- it "should cache authenticators" do
234
- Authentication.instance_variable_get(:@cache).size.should == 0
235
-
236
- anon_auth = Authentication.setup(nil)
237
- Authentication.instance_variable_get(:@cache).length.should == 1
238
-
239
- another_anon_auth = Authentication.setup(nil)
240
- Authentication.instance_variable_get(:@cache).length.should == 1
241
- another_anon_auth.should equal(anon_auth)
242
-
243
- user_auth = Authentication.setup(:username => 'frodo', :password => 'passw0rd')
244
- Authentication.instance_variable_get(:@cache).length.should == 2
245
- another_user_auth = Authentication.setup(:username => 'frodo', :password => 'passw0rd')
246
- Authentication.instance_variable_get(:@cache).length.should == 2
247
- another_user_auth.should equal(user_auth)
248
- end
249
-
250
- it "should reacquire expired tokens" do
251
- old_token = Authentication::Token.new('old/token==', Time.at(1))
252
- new_token = Authentication::Token.new('new/token==', Time.at(4))
253
-
254
- Time.stub!(:now).and_return(Time.at(0))
255
- old_auth = Authentication.setup(:username => 'frodo', :password => 'passw0rd')
256
-
257
- # old_auth will have to reacquire the token because the one it had initially will be expired
258
- old_auth.should_receive(:acquire_token).twice.and_return(old_token, new_token)
259
-
260
- old_auth.authenticate
261
- old_auth.token.should equal(old_token)
262
-
263
- Time.stub!(:now).and_return(Time.at(2))
264
-
265
- new_auth = Authentication.setup(:username => 'frodo', :password => 'passw0rd')
266
- new_auth.authenticate
267
-
268
- new_auth.should equal(old_auth)
269
- new_auth.token.should equal(new_token)
270
- end
271
-
272
- end
273
-
274
- describe Authentication::Token do
275
- it "should check that value is a well-formed token" do
276
- lambda { Authentication::Token.new("foo") }.
277
- should raise_error(AuthenticationError,
278
- /^Response from access control service doesn't seem to contain a valid authentication token/)
279
- end
280
-
281
- it "should ignore the rest of the body, if there is anything after the token (bug workaround)" do
282
- token = Authentication::Token.new('bWyFxQgby0gHyPWZ2LcIXnHgA1J5kALK4iM+QA==<html>....</html>')
283
- token.value.should == 'bWyFxQgby0gHyPWZ2LcIXnHgA1J5kALK4iM+QA=='
284
- end
285
-
286
- end
287
-
288
- end
289
-
@@ -1,161 +0,0 @@
1
- require "#{File.dirname(__FILE__)}/../../spec_helper"
2
-
3
- module DotNetServices
4
- describe MessageBuffer do
5
- describe "initialize(name, auth_data)" do
6
- it "should create a session" do
7
- Session.should_receive(:new).with('foo', :username => 'bar', :password => 'baz').and_return(:session)
8
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
9
- mb.session.should == :session
10
- end
11
-
12
- it "should be possible to specify polling_interval"
13
- end
14
-
15
- describe "register" do
16
- it "should register a message buffer" do
17
- response = Net::HTTPCreated.new(nil, nil, nil)
18
-
19
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
20
- mb.session.should_receive(:createmb).and_return(response)
21
- mb.register.should equal(mb)
22
- end
23
-
24
- it "should blow up if the response code is not 201 and the buffer cannot be queried" do
25
- create_response = Net::HTTPInternalServerError.new(nil, nil, nil)
26
- query_response = Net::HTTPNotFound.new(nil, nil, nil)
27
-
28
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
29
- mb.session.should_receive(:createmb).and_return(create_response)
30
- mb.session.should_receive(:get_from_relay).and_return(query_response)
31
- proc { mb.register }.should raise_error(
32
- RuntimeError, "Creating VMB failed. Service responded with Net::HTTPInternalServerError")
33
- end
34
-
35
- it "should not blow up if the response code to CREATEMB is not 201, byt the buffer can be queried" do
36
- create_response = Net::HTTPInternalServerError.new(nil, nil, nil)
37
- query_response = Net::HTTPSuccess.new(nil, nil, nil)
38
-
39
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
40
- mb.session.should_receive(:createmb).and_return(create_response)
41
- mb.session.should_receive(:get_from_relay).and_return(query_response)
42
- proc { mb.register }.should_not raise_error(
43
- RuntimeError, "Creating VMB failed. Service responded with Net::HTTPInternalServerError")
44
- end
45
-
46
- end
47
-
48
- describe "open(&block)" do
49
- it "should register the buffer if necessary" do
50
- block = lambda { :foo }
51
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
52
- mb.session.should_receive(:get_from_relay).and_return(Net::HTTPNotFound.new(nil, nil, nil))
53
- mb.should_receive(:register).and_return(mb)
54
- mb.open(&block)
55
- end
56
- end
57
-
58
- describe "poll" do
59
- it "should retrieve a single message from the buffer" do
60
- response = Net::HTTPOK.new(nil, nil, nil)
61
-
62
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
63
- mb.session.should_receive(:retrieve).with(:encoding => 'asreply', :timeout => nil).and_return(response)
64
-
65
- message = mb.poll
66
-
67
- message.should == response
68
- end
69
-
70
- it "should return nil if no no message was retrieved in the buffer" do
71
- response = Net::HTTPNoContent.new(nil, nil, nil)
72
-
73
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
74
- mb.session.should_receive(:retrieve).and_return(response)
75
-
76
- mb.poll.should be_nil
77
- end
78
-
79
- it "should recreate a buffer if the bus says it doesn't exist and poll again" do
80
- not_found_response = Net::HTTPNotFound.new(nil, nil, nil)
81
- created_response = Net::HTTPCreated.new(nil, nil, nil)
82
-
83
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
84
-
85
- mb.session.should_receive(:retrieve).with(:encoding => 'asreply', :timeout => nil).and_return(not_found_response)
86
- mb.session.should_receive(:createmb).and_return(created_response)
87
-
88
- message = mb.poll
89
-
90
- message.should == nil
91
- end
92
-
93
- end
94
-
95
- describe "delete()" do
96
- it "should send a DELETE request to the relay" do
97
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
98
- response = Net::HTTPNoContent.new(nil, nil, nil)
99
-
100
- mb.session.should_receive(:delete).and_return(response)
101
-
102
- mb.delete.should == mb
103
- end
104
-
105
- it "should do nothing if the response is NotFound (i.e., the VMB already doesn't exist"
106
-
107
- it "should blow up if response is not NoContent, and not NotFound" do
108
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
109
- response = Net::HTTPNotFound.new(nil, nil, nil)
110
-
111
- mb.session.should_receive(:delete).and_return(response)
112
-
113
- lambda { mb.delete }.should raise_error("Deleting VMB failed. Response was Net::HTTPNotFound")
114
- end
115
- end
116
-
117
- describe "expires()" do
118
- it "should do a GET to relay and return the value of 'expires' header" do
119
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
120
-
121
- response = Net::HTTPOK.new(nil, nil, nil)
122
- response.should_receive(:[]).with('expires').and_return("Thu, 01 Dec 2009 16:00:00 GMT")
123
-
124
- mb.session.should_receive(:get_from_relay).and_return(response)
125
-
126
- mb.expires.should == DateTime.parse("2009-12-01 16:00:00 Z")
127
- end
128
-
129
- it "should blow up if response is not 200" do
130
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
131
- response = Net::HTTPNotFound.new(nil, nil, nil)
132
- mb.session.should_receive(:get_from_relay).and_return(response)
133
-
134
- lambda { mb.expires }.should raise_error("Querying expiry status of VMB failed. Response was Net::HTTPNotFound")
135
- end
136
-
137
- it "should blow up if response has no expires header" do
138
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
139
- response = Net::HTTPOK.new(nil, nil, nil)
140
- response.should_receive(:[]).with('expires').and_return(nil)
141
- mb.session.should_receive(:get_from_relay).and_return(response)
142
-
143
- lambda { mb.expires }.should raise_error("Querying expiry status of VMB failed. Response doesn't have expires: header")
144
- end
145
- end
146
-
147
- describe "keep_alive" do
148
- it "should send an empty post to relay on buffer endpoint" do
149
- mb = MessageBuffer.new('foo', :username => 'bar', :password => 'baz')
150
- response = Net::HTTPOK.new(nil, nil, nil)
151
- mb.session.should_receive(:post_to_relay).with("\n").and_return(response)
152
- mb.keep_alive.should == mb
153
- end
154
- end
155
-
156
- describe "subscribe" do
157
-
158
- end
159
-
160
- end
161
- end