PageRenderTime 503ms CodeModel.GetById 61ms RepoModel.GetById 142ms app.codeStats 0ms

/spec/lib/gitlab/saml/user_spec.rb

https://gitlab.com/chrisbelyea/gitlab-ee
Ruby | 325 lines | 279 code | 46 blank | 0 comment | 0 complexity | 64ad6ff870f95e1c2bcc24c56db5fb21 MD5 | raw file
  1. require 'spec_helper'
  2. describe Gitlab::Saml::User, lib: true do
  3. let(:saml_user) { described_class.new(auth_hash) }
  4. let(:gl_user) { saml_user.gl_user }
  5. let(:uid) { 'my-uid' }
  6. let(:provider) { 'saml' }
  7. let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash, extra: { raw_info: OneLogin::RubySaml::Attributes.new({ 'groups' => %w(Developers Freelancers Designers) }) }) }
  8. let(:info_hash) do
  9. {
  10. name: 'John',
  11. email: 'john@mail.com'
  12. }
  13. end
  14. let(:ldap_user) { Gitlab::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
  15. describe '#save' do
  16. def stub_omniauth_config(messages)
  17. allow(Gitlab.config.omniauth).to receive_messages(messages)
  18. end
  19. def stub_ldap_config(messages)
  20. allow(Gitlab::LDAP::Config).to receive_messages(messages)
  21. end
  22. def stub_basic_saml_config
  23. allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', args: {} } })
  24. end
  25. def stub_saml_group_config(groups)
  26. allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', groups_attribute: 'groups', external_groups: groups, args: {} } })
  27. end
  28. def stub_saml_admin_group_config(groups)
  29. allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', groups_attribute: 'groups', admin_groups: groups, args: {} } })
  30. end
  31. before { stub_basic_saml_config }
  32. describe 'account exists on server' do
  33. before { stub_omniauth_config({ allow_single_sign_on: ['saml'], auto_link_saml_user: true }) }
  34. let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
  35. context 'and should bind with SAML' do
  36. it 'adds the SAML identity to the existing user' do
  37. saml_user.save
  38. expect(gl_user).to be_valid
  39. expect(gl_user).to eq existing_user
  40. identity = gl_user.identities.first
  41. expect(identity.extern_uid).to eql uid
  42. expect(identity.provider).to eql 'saml'
  43. end
  44. end
  45. context 'external groups' do
  46. context 'are defined' do
  47. it 'marks the user as external' do
  48. stub_saml_group_config(%w(Freelancers))
  49. saml_user.save
  50. expect(gl_user).to be_valid
  51. expect(gl_user.external).to be_truthy
  52. end
  53. end
  54. before { stub_saml_group_config(%w(Interns)) }
  55. context 'are defined but the user does not belong there' do
  56. it 'does not mark the user as external' do
  57. saml_user.save
  58. expect(gl_user).to be_valid
  59. expect(gl_user.external).to be_falsey
  60. end
  61. end
  62. context 'user was external, now should not be' do
  63. it 'makes user internal' do
  64. existing_user.update_attribute('external', true)
  65. saml_user.save
  66. expect(gl_user).to be_valid
  67. expect(gl_user.external).to be_falsey
  68. end
  69. end
  70. end
  71. context 'admin groups' do
  72. context 'are defined' do
  73. it 'marks the user as admin' do
  74. stub_saml_admin_group_config(%w(Developers))
  75. saml_user.save
  76. expect(gl_user).to be_valid
  77. expect(gl_user.admin).to be_truthy
  78. end
  79. end
  80. before { stub_saml_admin_group_config(%w(Admins)) }
  81. context 'are defined but the user does not belong there' do
  82. it 'does not mark the user as admin' do
  83. saml_user.save
  84. expect(gl_user).to be_valid
  85. expect(gl_user.admin).to be_falsey
  86. end
  87. end
  88. context 'user was admin, now should not be' do
  89. it 'makes user non admin' do
  90. existing_user.update_attribute('admin', true)
  91. saml_user.save
  92. expect(gl_user).to be_valid
  93. expect(gl_user.admin).to be_falsey
  94. end
  95. end
  96. end
  97. end
  98. describe 'no account exists on server' do
  99. shared_examples 'to verify compliance with allow_single_sign_on' do
  100. context 'with allow_single_sign_on enabled' do
  101. before { stub_omniauth_config(allow_single_sign_on: ['saml']) }
  102. it 'creates a user from SAML' do
  103. saml_user.save
  104. expect(gl_user).to be_valid
  105. identity = gl_user.identities.first
  106. expect(identity.extern_uid).to eql uid
  107. expect(identity.provider).to eql 'saml'
  108. end
  109. end
  110. context 'with allow_single_sign_on default (["saml"])' do
  111. before { stub_omniauth_config(allow_single_sign_on: ['saml']) }
  112. it 'does not throw an error' do
  113. expect{ saml_user.save }.not_to raise_error
  114. end
  115. end
  116. context 'with allow_single_sign_on disabled' do
  117. before { stub_omniauth_config(allow_single_sign_on: false) }
  118. it 'throws an error' do
  119. expect{ saml_user.save }.to raise_error StandardError
  120. end
  121. end
  122. end
  123. context 'external groups' do
  124. context 'are defined' do
  125. it 'marks the user as external' do
  126. stub_saml_group_config(%w(Freelancers))
  127. saml_user.save
  128. expect(gl_user).to be_valid
  129. expect(gl_user.external).to be_truthy
  130. end
  131. end
  132. context 'are defined but the user does not belong there' do
  133. it 'does not mark the user as external' do
  134. stub_saml_group_config(%w(Interns))
  135. saml_user.save
  136. expect(gl_user).to be_valid
  137. expect(gl_user.external).to be_falsey
  138. end
  139. end
  140. end
  141. context 'admin groups' do
  142. context 'are defined' do
  143. it 'marks the user as admin' do
  144. stub_saml_admin_group_config(%w(Developers))
  145. saml_user.save
  146. expect(gl_user).to be_valid
  147. expect(gl_user.admin).to be_truthy
  148. end
  149. end
  150. context 'are defined but the user does not belong there' do
  151. it 'does not mark the user as admin' do
  152. stub_saml_admin_group_config(%w(Admins))
  153. saml_user.save
  154. expect(gl_user).to be_valid
  155. expect(gl_user.admin).to be_falsey
  156. end
  157. end
  158. end
  159. context 'with auto_link_ldap_user disabled (default)' do
  160. before { stub_omniauth_config({ auto_link_ldap_user: false, auto_link_saml_user: false, allow_single_sign_on: ['saml'] }) }
  161. include_examples 'to verify compliance with allow_single_sign_on'
  162. end
  163. context 'with auto_link_ldap_user enabled' do
  164. before { stub_omniauth_config({ auto_link_ldap_user: true, auto_link_saml_user: false }) }
  165. context 'and at least one LDAP provider is defined' do
  166. before { stub_ldap_config(providers: %w(ldapmain)) }
  167. context 'and a corresponding LDAP person' do
  168. before do
  169. allow(ldap_user).to receive(:uid) { uid }
  170. allow(ldap_user).to receive(:username) { uid }
  171. allow(ldap_user).to receive(:email) { %w(john@mail.com john2@example.com) }
  172. allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' }
  173. allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user)
  174. allow(Gitlab::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user)
  175. end
  176. context 'and no account for the LDAP user' do
  177. it 'creates a user with dual LDAP and SAML identities' do
  178. saml_user.save
  179. expect(gl_user).to be_valid
  180. expect(gl_user.username).to eql uid
  181. expect(gl_user.email).to eql 'john@mail.com'
  182. expect(gl_user.identities.length).to eql 2
  183. identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
  184. expect(identities_as_hash).to match_array([ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
  185. { provider: 'saml', extern_uid: uid }
  186. ])
  187. end
  188. end
  189. context 'and LDAP user has an account already' do
  190. before do
  191. create(:omniauth_user,
  192. email: 'john@mail.com',
  193. extern_uid: 'uid=user1,ou=People,dc=example',
  194. provider: 'ldapmain',
  195. username: 'john')
  196. end
  197. it 'adds the omniauth identity to the LDAP account' do
  198. saml_user.save
  199. expect(gl_user).to be_valid
  200. expect(gl_user.username).to eql 'john'
  201. expect(gl_user.email).to eql 'john@mail.com'
  202. expect(gl_user.identities.length).to eql 2
  203. identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
  204. expect(identities_as_hash).to match_array([ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
  205. { provider: 'saml', extern_uid: uid }
  206. ])
  207. end
  208. it 'saves successfully on subsequent tries, when both identities are present' do
  209. saml_user.save
  210. local_saml_user = described_class.new(auth_hash)
  211. local_saml_user.save
  212. expect(local_saml_user.gl_user).to be_valid
  213. expect(local_saml_user.gl_user).to be_persisted
  214. end
  215. end
  216. context 'user has SAML user, and wants to add their LDAP identity' do
  217. it 'adds the LDAP identity to the existing SAML user' do
  218. create(:omniauth_user, email: 'john@mail.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'saml', username: 'john')
  219. local_hash = OmniAuth::AuthHash.new(uid: 'uid=user1,ou=People,dc=example', provider: provider, info: info_hash)
  220. local_saml_user = described_class.new(local_hash)
  221. local_saml_user.save
  222. local_gl_user = local_saml_user.gl_user
  223. expect(local_gl_user).to be_valid
  224. expect(local_gl_user.identities.length).to eql 2
  225. identities_as_hash = local_gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
  226. expect(identities_as_hash).to match_array([ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
  227. { provider: 'saml', extern_uid: 'uid=user1,ou=People,dc=example' }
  228. ])
  229. end
  230. end
  231. end
  232. end
  233. end
  234. end
  235. describe 'blocking' do
  236. before { stub_omniauth_config({ allow_single_sign_on: ['saml'], auto_link_saml_user: true }) }
  237. context 'signup with SAML only' do
  238. context 'dont block on create' do
  239. before { stub_omniauth_config(block_auto_created_users: false) }
  240. it 'does not block the user' do
  241. saml_user.save
  242. expect(gl_user).to be_valid
  243. expect(gl_user).not_to be_blocked
  244. end
  245. end
  246. context 'block on create' do
  247. before { stub_omniauth_config(block_auto_created_users: true) }
  248. it 'blocks user' do
  249. saml_user.save
  250. expect(gl_user).to be_valid
  251. expect(gl_user).to be_blocked
  252. end
  253. end
  254. end
  255. context 'sign-in' do
  256. before do
  257. saml_user.save
  258. saml_user.gl_user.activate
  259. end
  260. context 'dont block on create' do
  261. before { stub_omniauth_config(block_auto_created_users: false) }
  262. it do
  263. saml_user.save
  264. expect(gl_user).to be_valid
  265. expect(gl_user).not_to be_blocked
  266. end
  267. end
  268. context 'block on create' do
  269. before { stub_omniauth_config(block_auto_created_users: true) }
  270. it do
  271. saml_user.save
  272. expect(gl_user).to be_valid
  273. expect(gl_user).not_to be_blocked
  274. end
  275. end
  276. end
  277. end
  278. end
  279. end