maestrano-ruby-test 0.8.3

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.
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