maestrano-ruby-test 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +45 -0
  5. data/LICENSE +21 -0
  6. data/README.md +794 -0
  7. data/Rakefile +40 -0
  8. data/bin/maestrano-console +9 -0
  9. data/lib/maestrano.rb +271 -0
  10. data/lib/maestrano/account/bill.rb +14 -0
  11. data/lib/maestrano/account/recurring_bill.rb +14 -0
  12. data/lib/maestrano/api/error/authentication_error.rb +8 -0
  13. data/lib/maestrano/api/error/base_error.rb +24 -0
  14. data/lib/maestrano/api/error/connection_error.rb +8 -0
  15. data/lib/maestrano/api/error/invalid_request_error.rb +14 -0
  16. data/lib/maestrano/api/list_object.rb +37 -0
  17. data/lib/maestrano/api/object.rb +187 -0
  18. data/lib/maestrano/api/operation/base.rb +215 -0
  19. data/lib/maestrano/api/operation/create.rb +18 -0
  20. data/lib/maestrano/api/operation/delete.rb +13 -0
  21. data/lib/maestrano/api/operation/list.rb +18 -0
  22. data/lib/maestrano/api/operation/update.rb +59 -0
  23. data/lib/maestrano/api/resource.rb +47 -0
  24. data/lib/maestrano/api/util.rb +122 -0
  25. data/lib/maestrano/open_struct.rb +11 -0
  26. data/lib/maestrano/saml/attribute_value.rb +15 -0
  27. data/lib/maestrano/saml/metadata.rb +64 -0
  28. data/lib/maestrano/saml/request.rb +93 -0
  29. data/lib/maestrano/saml/response.rb +201 -0
  30. data/lib/maestrano/saml/schemas/saml20assertion_schema.xsd +283 -0
  31. data/lib/maestrano/saml/schemas/saml20protocol_schema.xsd +302 -0
  32. data/lib/maestrano/saml/schemas/xenc_schema.xsd +146 -0
  33. data/lib/maestrano/saml/schemas/xmldsig_schema.xsd +318 -0
  34. data/lib/maestrano/saml/settings.rb +37 -0
  35. data/lib/maestrano/saml/validation_error.rb +7 -0
  36. data/lib/maestrano/sso.rb +86 -0
  37. data/lib/maestrano/sso/base_group.rb +31 -0
  38. data/lib/maestrano/sso/base_membership.rb +25 -0
  39. data/lib/maestrano/sso/base_user.rb +75 -0
  40. data/lib/maestrano/sso/group.rb +24 -0
  41. data/lib/maestrano/sso/session.rb +107 -0
  42. data/lib/maestrano/sso/user.rb +34 -0
  43. data/lib/maestrano/version.rb +3 -0
  44. data/lib/maestrano/xml_security/signed_document.rb +170 -0
  45. data/maestrano.gemspec +32 -0
  46. data/maestrano.png +0 -0
  47. data/test/helpers/api_helpers.rb +115 -0
  48. data/test/helpers/saml_helpers.rb +62 -0
  49. data/test/maestrano/account/bill_test.rb +48 -0
  50. data/test/maestrano/account/recurring_bill_test.rb +49 -0
  51. data/test/maestrano/api/list_object_test.rb +20 -0
  52. data/test/maestrano/api/object_test.rb +28 -0
  53. data/test/maestrano/api/resource_test.rb +343 -0
  54. data/test/maestrano/api/util_test.rb +31 -0
  55. data/test/maestrano/maestrano_test.rb +260 -0
  56. data/test/maestrano/open_struct_test.rb +10 -0
  57. data/test/maestrano/saml/request_test.rb +168 -0
  58. data/test/maestrano/saml/response_test.rb +290 -0
  59. data/test/maestrano/saml/settings_test.rb +51 -0
  60. data/test/maestrano/sso/base_group_test.rb +54 -0
  61. data/test/maestrano/sso/base_membership_test.rb +45 -0
  62. data/test/maestrano/sso/base_user_test.rb +114 -0
  63. data/test/maestrano/sso/group_test.rb +47 -0
  64. data/test/maestrano/sso/session_test.rb +161 -0
  65. data/test/maestrano/sso/user_test.rb +65 -0
  66. data/test/maestrano/sso_test.rb +105 -0
  67. data/test/maestrano/xml_security/signed_document.rb +163 -0
  68. data/test/support/saml/certificates/certificate1 +12 -0
  69. data/test/support/saml/certificates/r1_certificate2_base64 +1 -0
  70. data/test/support/saml/responses/adfs_response_sha1.xml +46 -0
  71. data/test/support/saml/responses/adfs_response_sha256.xml +46 -0
  72. data/test/support/saml/responses/adfs_response_sha384.xml +46 -0
  73. data/test/support/saml/responses/adfs_response_sha512.xml +46 -0
  74. data/test/support/saml/responses/no_signature_ns.xml +48 -0
  75. data/test/support/saml/responses/open_saml_response.xml +56 -0
  76. data/test/support/saml/responses/r1_response6.xml.base64 +1 -0
  77. data/test/support/saml/responses/response1.xml.base64 +1 -0
  78. data/test/support/saml/responses/response2.xml.base64 +79 -0
  79. data/test/support/saml/responses/response3.xml.base64 +66 -0
  80. data/test/support/saml/responses/response4.xml.base64 +93 -0
  81. data/test/support/saml/responses/response5.xml.base64 +102 -0
  82. data/test/support/saml/responses/response_with_ampersands.xml +139 -0
  83. data/test/support/saml/responses/response_with_ampersands.xml.base64 +93 -0
  84. data/test/support/saml/responses/response_with_multiple_attribute_values.xml +57 -0
  85. data/test/support/saml/responses/simple_saml_php.xml +71 -0
  86. data/test/support/saml/responses/starfield_response.xml.base64 +1 -0
  87. data/test/support/saml/responses/wrapped_response_2.xml.base64 +150 -0
  88. data/test/test_helper.rb +47 -0
  89. metadata +315 -0
@@ -0,0 +1,47 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Maestrano
4
+ module SSO
5
+ class GroupTest < Test::Unit::TestCase
6
+ setup do
7
+ @group = mock('group')
8
+ class << @group
9
+ include Maestrano::SSO::Group
10
+ end
11
+ end
12
+
13
+ context "find_for_maestrano_auth" do
14
+ should "raise an error if not overriden" do
15
+ assert_raise(NoMethodError.new("You need to override find_for_maestrano_auth in your Mocha::Mock model")) do
16
+ @group.find_for_maestrano_auth({})
17
+ end
18
+ end
19
+
20
+ should "execute properly otherwise" do
21
+ def @group.find_for_maestrano_auth(auth); return true; end
22
+ assert_nothing_thrown do
23
+ @group.find_for_maestrano_auth({})
24
+ end
25
+ end
26
+ end
27
+
28
+ context "maestrano?" do
29
+ should "raise an error if no provider attribute and not overriden" do
30
+ assert_raise(NoMethodError.new("You need to override maestrano? in your Mocha::Mock model")) do
31
+ @group.maestrano?
32
+ end
33
+ end
34
+
35
+ should "return true if the provider is 'maestrano'" do
36
+ @group.stubs(:provider).returns('maestrano')
37
+ assert @group.maestrano?
38
+ end
39
+
40
+ should "return false if the provider is something else" do
41
+ @group.stubs(:provider).returns('someprovider')
42
+ assert !@group.maestrano?
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,161 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Maestrano
4
+ module SSO
5
+ class SessionTest < Test::Unit::TestCase
6
+ setup do
7
+ @mno_session = {
8
+ uid: 'usr-1',
9
+ session: 'g4dfg4fdg8378d6acf45',
10
+ session_recheck: Time.now.utc.iso8601,
11
+ group_uid: 'cld-2'
12
+ }
13
+ @session = {
14
+ maestrano: Base64.encode64(@mno_session.to_json)
15
+ }
16
+ end
17
+
18
+ should "initialize the sso session properly" do
19
+ sso_session = Maestrano::SSO::Session.new(@session)
20
+ assert_equal sso_session.uid, @mno_session[:uid]
21
+ assert_equal sso_session.session_token, @mno_session[:session]
22
+ assert_equal sso_session.recheck, Time.iso8601(@mno_session[:session_recheck])
23
+ assert_equal sso_session.group_uid, @mno_session[:group_uid]
24
+ end
25
+
26
+ context "from_user_auth_hash" do
27
+ should "set the session correctly" do
28
+ sso_session = {}
29
+ auth = {
30
+ extra: {
31
+ session: {
32
+ uid: 'usr-1',
33
+ token: '15fg6d',
34
+ recheck: Time.now,
35
+ group_uid: 'cld-3'
36
+ }
37
+ }
38
+ }
39
+ sso_session = Maestrano::SSO::Session.from_user_auth_hash(@session,auth)
40
+ assert_equal sso_session.uid, auth[:extra][:session][:uid]
41
+ assert_equal sso_session.session_token, auth[:extra][:session][:token]
42
+ assert_equal sso_session.recheck.utc.iso8601, auth[:extra][:session][:recheck].utc.iso8601
43
+ assert_equal sso_session.group_uid, auth[:extra][:session][:group_uid]
44
+ end
45
+ end
46
+
47
+
48
+ context "remote_check_required?" do
49
+ setup do
50
+ @sso_session = Maestrano::SSO::Session.new(@session)
51
+ end
52
+
53
+ should "should return true if uid is missing" do
54
+ @sso_session.uid = nil
55
+ assert @sso_session.remote_check_required?
56
+ end
57
+
58
+ should "should return true if session_token is missing" do
59
+ @sso_session.session_token = nil
60
+ assert @sso_session.remote_check_required?
61
+ end
62
+
63
+ should "should return true if recheck is missing" do
64
+ @sso_session.recheck = nil
65
+ assert @sso_session.remote_check_required?
66
+ end
67
+
68
+ should "return true if now is after recheck" do
69
+ Timecop.freeze(@sso_session.recheck + 60) do
70
+ assert @sso_session.remote_check_required?
71
+ end
72
+ end
73
+
74
+ should "return false if now is before recheck" do
75
+ Timecop.freeze(@sso_session.recheck - 60) do
76
+ assert !@sso_session.remote_check_required?
77
+ end
78
+ end
79
+ end
80
+
81
+ context "perform_remote_check" do
82
+ setup do
83
+ @sso_session = Maestrano::SSO::Session.new(@session)
84
+ end
85
+
86
+ should "update the session recheck and return true if valid" do
87
+ recheck = @sso_session.recheck + 600
88
+ RestClient.stubs(:get).returns({'valid' => true, 'recheck' => recheck.utc.iso8601 }.to_json)
89
+ assert @sso_session.perform_remote_check
90
+ assert_equal @sso_session.recheck, recheck
91
+ end
92
+
93
+ should "leave the session recheck unchanged and return false if invalid" do
94
+ recheck = @sso_session.recheck
95
+ RestClient.stubs(:get).returns({'valid' => false, 'recheck' => (recheck + 600).utc.iso8601 }.to_json)
96
+ assert !@sso_session.perform_remote_check
97
+ assert_equal @sso_session.recheck, recheck
98
+ end
99
+ end
100
+
101
+ context "valid?" do
102
+ setup do
103
+ @sso_session = Maestrano::SSO::Session.new(@session)
104
+ Maestrano.configure { |c| c.sso.slo_enabled = true }
105
+ end
106
+
107
+ should "return true if Single Logout is disabled" do
108
+ Maestrano.configure { |c| c.sso.slo_enabled = false }
109
+ @sso_session.stubs(:remote_check_required?).returns(true)
110
+ @sso_session.stubs(:perform_remote_check).returns(false)
111
+ assert @sso_session.valid?
112
+ end
113
+
114
+ should "return true if_session is enabled and session is nil" do
115
+ sso_session = Maestrano::SSO::Session.new(nil)
116
+ assert sso_session.valid?(if_session: true)
117
+ end
118
+
119
+ should "return true if_session is enabled and session is empty" do
120
+ sso_session = Maestrano::SSO::Session.new({})
121
+ assert sso_session.valid?(if_session: true)
122
+ end
123
+
124
+ should "return true if no remote_check_required?" do
125
+ @sso_session.stubs(:remote_check_required?).returns(false)
126
+ assert @sso_session.valid?
127
+ assert @sso_session.valid?(if_session: true)
128
+ end
129
+
130
+ should "return true if remote_check_required? and valid" do
131
+ @sso_session.stubs(:remote_check_required?).returns(true)
132
+ @sso_session.stubs(:perform_remote_check).returns(true)
133
+ assert @sso_session.valid?
134
+ assert @sso_session.valid?(if_session: true)
135
+ end
136
+
137
+ should "update maestrano session with recheck timestamp if remote_check_required? and valid" do
138
+ recheck = (@sso_session.recheck + 600)
139
+ @sso_session.recheck = recheck
140
+ @sso_session.stubs(:remote_check_required?).returns(true)
141
+ @sso_session.stubs(:perform_remote_check).returns(true)
142
+ @sso_session.valid?
143
+ assert_equal JSON.parse(Base64.decode64(@session[:maestrano]))['session_recheck'], recheck.utc.iso8601
144
+ end
145
+
146
+ should "return false if remote_check_required? and invalid" do
147
+ @sso_session.stubs(:remote_check_required?).returns(true)
148
+ @sso_session.stubs(:perform_remote_check).returns(false)
149
+ assert_false @sso_session.valid?
150
+ assert_false @sso_session.valid?(if_session: true)
151
+ end
152
+
153
+ should "return false if internal session is nil" do
154
+ sso_session = Maestrano::SSO::Session.new(nil)
155
+ assert_false @sso_session.valid?
156
+ end
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Maestrano
4
+ module SSO
5
+ class UserTest < Test::Unit::TestCase
6
+ setup do
7
+ @user = mock('user')
8
+ class << @user
9
+ include Maestrano::SSO::User
10
+ end
11
+ end
12
+
13
+ context "find_for_maestrano_auth" do
14
+ should "raise an error if not overriden" do
15
+ assert_raise(NoMethodError.new("You need to override find_for_maestrano_auth in your Mocha::Mock model")) do
16
+ @user.find_for_maestrano_auth({})
17
+ end
18
+ end
19
+
20
+ should "execute properly otherwise" do
21
+ def @user.find_for_maestrano_auth(auth); return true; end
22
+ assert_nothing_thrown do
23
+ @user.find_for_maestrano_auth({})
24
+ end
25
+ end
26
+ end
27
+
28
+ context "maestrano?" do
29
+ should "raise an error if no provider attribute and not overriden" do
30
+ assert_raise(NoMethodError.new("You need to override maestrano? in your Mocha::Mock model")) do
31
+ @user.maestrano?
32
+ end
33
+ end
34
+
35
+ should "return true if the provider is 'maestrano'" do
36
+ @user.stubs(:provider).returns('maestrano')
37
+ assert @user.maestrano?
38
+ end
39
+
40
+ should "return false if the provider is something else" do
41
+ @user.stubs(:provider).returns('someprovider')
42
+ assert !@user.maestrano?
43
+ end
44
+ end
45
+
46
+ context "maestrano_session_valid?" do
47
+ should "return true if the sso session is valid" do
48
+ session = {}
49
+ sso_session = mock('sso_session')
50
+ Maestrano::SSO::Session.stubs(:new).with(session).returns(sso_session)
51
+ sso_session.stubs(:valid?).returns(true)
52
+ assert @user.maestrano_session_valid?(session)
53
+ end
54
+
55
+ should "return false if the sso session is invalid" do
56
+ session = {}
57
+ sso_session = mock('sso_session')
58
+ Maestrano::SSO::Session.stubs(:new).with(session).returns(sso_session)
59
+ sso_session.stubs(:valid?).returns(false)
60
+ assert !@user.maestrano_session_valid?(session)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,105 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Maestrano
4
+ class SSOTest < Test::Unit::TestCase
5
+ include SamlTestHelper
6
+
7
+ setup do
8
+ Maestrano.config = nil
9
+ Maestrano.configure { |config| config.environment = 'production' }
10
+ end
11
+
12
+ should "return the right init_url" do
13
+ assert Maestrano::SSO.init_url == "http://localhost:3000/maestrano/auth/saml/init"
14
+ end
15
+
16
+ should "return the right consume_url" do
17
+ assert Maestrano::SSO.consume_url == "http://localhost:3000/maestrano/auth/saml/consume"
18
+ end
19
+
20
+ should "return the right logout_url" do
21
+ assert Maestrano::SSO.logout_url == "https://maestrano.com/app_logout"
22
+ end
23
+
24
+ should "return the right unauthorized_url" do
25
+ assert Maestrano::SSO.unauthorized_url == "https://maestrano.com/app_access_unauthorized"
26
+ end
27
+
28
+ should "return the right idp_url" do
29
+ assert Maestrano::SSO.idp_url == "https://maestrano.com/api/v1/auth/saml"
30
+ end
31
+
32
+ should "return the right session_check_url" do
33
+ assert Maestrano::SSO.session_check_url('usr-1','f9ds8fdg7f89') == "https://maestrano.com/api/v1/auth/saml/usr-1?session=f9ds8fdg7f89"
34
+ end
35
+
36
+ should "return the right enabled parameter" do
37
+ assert Maestrano::SSO.enabled? == !!Maestrano.param('sso.enabled')
38
+ end
39
+
40
+ should "return the right saml_settings" do
41
+ settings = Maestrano::SSO.saml_settings
42
+ assert settings.assertion_consumer_service_url == Maestrano::SSO.consume_url
43
+ assert settings.issuer == Maestrano.param('api.id')
44
+ assert settings.idp_sso_target_url == Maestrano::SSO.idp_url
45
+ assert settings.idp_cert_fingerprint == Maestrano.param('sso_x509_fingerprint')
46
+ assert settings.name_identifier_format == Maestrano.param('sso_name_id_format')
47
+ end
48
+
49
+ should "build the right saml request" do
50
+ request = mock('request')
51
+ Maestrano::Saml::Request.stubs(:new).with(group_id: "cld-3").returns(request)
52
+ assert Maestrano::SSO.build_request(group_id: "cld-3") == request
53
+ end
54
+
55
+ should "build the right saml response" do
56
+ response = mock('response')
57
+ Maestrano::Saml::Response.stubs(:new).with(response_document).returns(response)
58
+ response = Maestrano::SSO.build_response(response_document)
59
+ assert Maestrano::SSO.build_response(response_document) == response
60
+ end
61
+
62
+ context "session management" do
63
+ setup do
64
+ @session = {}
65
+ @auth = {
66
+ extra: {
67
+ session: {
68
+ uid: 'usr-1',
69
+ token: '15fg6d',
70
+ recheck: Time.now,
71
+ group_uid: 'cld-3'
72
+ }
73
+ }
74
+ }
75
+ end
76
+
77
+ should "set the session correctly" do
78
+ Maestrano::SSO.set_session(@session,@auth)
79
+ decrypt_session = JSON.parse(Base64.decode64(@session[:maestrano]))
80
+ assert_equal decrypt_session['uid'], @auth[:extra][:session][:uid]
81
+ assert_equal decrypt_session['session'], @auth[:extra][:session][:token]
82
+ assert_equal decrypt_session['session_recheck'], @auth[:extra][:session][:recheck].utc.iso8601
83
+ assert_equal decrypt_session['group_uid'], @auth[:extra][:session][:group_uid]
84
+ end
85
+
86
+ should "unset the session correctly" do
87
+ Maestrano::SSO.set_session(@session,@auth)
88
+ Maestrano::SSO.clear_session(@session)
89
+ assert @session[:maestrano].nil?
90
+ end
91
+
92
+ should "unset the session if key is a string" do
93
+ @session['maestrano'] = "bla"
94
+ Maestrano::SSO.clear_session(@session)
95
+ assert @session["maestrano"].nil?
96
+ end
97
+
98
+ should "alias clear_session as unset_session" do
99
+ Maestrano::SSO.set_session(@session,@auth)
100
+ Maestrano::SSO.unset_session(@session)
101
+ assert @session[:maestrano].nil?
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,163 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Maestrano
4
+ module XMLSecurity
5
+ class XmlSecurityTest < Test::Unit::TestCase
6
+ include XMLSecurity
7
+
8
+ context "XmlSecurity" do
9
+ setup do
10
+ @document = Maestrano::XMLSecurity::SignedDocument.new(Base64.decode64(response_document))
11
+ @base64cert = @document.elements["//ds:X509Certificate"].text
12
+ end
13
+
14
+ should "should run validate without throwing NS related exceptions" do
15
+ assert !@document.validate_signature(@base64cert, true)
16
+ end
17
+
18
+ should "should run validate with throwing NS related exceptions" do
19
+ assert_raise(Maestrano::Saml::ValidationError) do
20
+ @document.validate_signature(@base64cert, false)
21
+ end
22
+ end
23
+
24
+ should "not raise an error when softly validating the document multiple times" do
25
+ assert_nothing_raised do
26
+ 2.times { @document.validate_signature(@base64cert, true) }
27
+ end
28
+ end
29
+
30
+ should "should raise Fingerprint mismatch" do
31
+ exception = assert_raise(Maestrano::Saml::ValidationError) do
32
+ @document.validate_document("no:fi:ng:er:pr:in:t", false)
33
+ end
34
+ assert_equal("Fingerprint mismatch", exception.message)
35
+ end
36
+
37
+ should "should raise Digest mismatch" do
38
+ exception = assert_raise(Maestrano::Saml::ValidationError) do
39
+ @document.validate_signature(@base64cert, false)
40
+ end
41
+ assert_equal("Digest mismatch", exception.message)
42
+ end
43
+
44
+ should "should raise Key validation error" do
45
+ response = Base64.decode64(response_document)
46
+ response.sub!("<ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>",
47
+ "<ds:DigestValue>b9xsAXLsynugg3Wc1CI3kpWku+0=</ds:DigestValue>")
48
+ document = Maestrano::XMLSecurity::SignedDocument.new(response)
49
+ base64cert = document.elements["//ds:X509Certificate"].text
50
+ exception = assert_raise(Maestrano::Saml::ValidationError) do
51
+ document.validate_signature(base64cert, false)
52
+ end
53
+ assert_equal("Key validation error", exception.message)
54
+ end
55
+
56
+ should "raise validation error when the X509Certificate is missing" do
57
+ response = Base64.decode64(response_document)
58
+ response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
59
+ document = Maestrano::XMLSecurity::SignedDocument.new(response)
60
+ exception = assert_raise(Maestrano::Saml::ValidationError) do
61
+ document.validate_document("a fingerprint", false) # The fingerprint isn't relevant to this test
62
+ end
63
+ assert_equal("Certificate element missing in response (ds:X509Certificate)", exception.message)
64
+ end
65
+ end
66
+
67
+ context "Algorithms" do
68
+ should "validate using SHA1" do
69
+ @document = Maestrano::XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
70
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
71
+ end
72
+
73
+ should "validate using SHA256" do
74
+ @document = Maestrano::XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false))
75
+ assert @document.validate_document("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
76
+ end
77
+
78
+ should "validate using SHA384" do
79
+ @document = Maestrano::XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false))
80
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
81
+ end
82
+
83
+ should "validate using SHA512" do
84
+ @document = Maestrano::XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false))
85
+ assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
86
+ end
87
+ end
88
+
89
+ context "XmlSecurity::SignedDocument" do
90
+
91
+ context "#extract_inclusive_namespaces" do
92
+ should "support explicit namespace resolution for exclusive canonicalization" do
93
+ response = fixture(:open_saml_response, false)
94
+ document = Maestrano::XMLSecurity::SignedDocument.new(response)
95
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
96
+
97
+ assert_equal %w[ xs ], inclusive_namespaces
98
+ end
99
+
100
+ should "support implicit namespace resolution for exclusive canonicalization" do
101
+ response = fixture(:no_signature_ns, false)
102
+ document = Maestrano::XMLSecurity::SignedDocument.new(response)
103
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
104
+
105
+ assert_equal %w[ #default saml ds xs xsi ], inclusive_namespaces
106
+ end
107
+
108
+ should_eventually 'support inclusive canonicalization' do
109
+
110
+ response = Maestrano::Saml::Response.new(fixture("tdnf_response.xml"))
111
+ response.stubs(:conditions).returns(nil)
112
+ assert !response.is_valid?
113
+ settings = Maestrano::Saml::Settings.new
114
+ assert !response.is_valid?
115
+ response.settings = settings
116
+ assert !response.is_valid?
117
+ settings.idp_cert_fingerprint = "e6 38 9a 20 b7 4f 13 db 6a bc b1 42 6a e7 52 1d d6 56 d4 1b".upcase.gsub(" ", ":")
118
+ assert response.validate!
119
+ end
120
+
121
+ should "return an empty list when inclusive namespace element is missing" do
122
+ response = fixture(:no_signature_ns, false)
123
+ response.slice! %r{<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/>}
124
+
125
+ document = Maestrano::XMLSecurity::SignedDocument.new(response)
126
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
127
+
128
+ assert inclusive_namespaces.empty?
129
+ end
130
+ end
131
+
132
+ context "StarfieldTMS" do
133
+ setup do
134
+ @response = Maestrano::Saml::Response.new(fixture(:starfield_response))
135
+ @response.settings = Maestrano::Saml::Settings.new(
136
+ :idp_cert_fingerprint => "8D:BA:53:8E:A3:B6:F9:F1:69:6C:BB:D9:D8:BD:41:B3:AC:4F:9D:4D"
137
+ )
138
+ end
139
+
140
+ should "be able to validate a good response" do
141
+ Timecop.freeze Time.parse('2012-11-28 17:55:00 UTC') do
142
+ assert @response.validate!
143
+ end
144
+ end
145
+
146
+ should "fail before response is valid" do
147
+ Timecop.freeze Time.parse('2012-11-20 17:55:00 UTC') do
148
+ assert ! @response.is_valid?
149
+ end
150
+ end
151
+
152
+ should "fail after response expires" do
153
+ Timecop.freeze Time.parse('2012-11-30 17:55:00 UTC') do
154
+ assert ! @response.is_valid?
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+
161
+ end
162
+ end
163
+ end