PageRenderTime 28ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/gitlab/auth.rb

https://gitlab.com/tagyangyang/gitlab-ee
Ruby | 124 lines | 90 code | 24 blank | 10 comment | 33 complexity | ed88d36fe0ed6b73132267da1961cf88 MD5 | raw file
  1. module Gitlab
  2. module Auth
  3. Result = Struct.new(:user, :type)
  4. class << self
  5. def find_for_git_client(login, password, project:, ip:)
  6. raise "Must provide an IP for rate limiting" if ip.nil?
  7. result = Result.new
  8. if valid_ci_request?(login, password, project)
  9. result.type = :ci
  10. else
  11. result = populate_result(login, password)
  12. end
  13. success = result.user.present? || [:ci, :missing_personal_token].include?(result.type)
  14. rate_limit!(ip, success: success, login: login)
  15. result
  16. end
  17. def find_with_user_password(login, password)
  18. user = User.by_login(login)
  19. if Devise.omniauth_providers.include?(:kerberos)
  20. kerberos_user = Gitlab::Kerberos::Authentication.login(login, password)
  21. return kerberos_user if kerberos_user
  22. end
  23. # If no user is found, or it's an LDAP server, try LDAP.
  24. # LDAP users are only authenticated via LDAP
  25. if user.nil? || user.ldap_user?
  26. # Second chance - try LDAP authentication
  27. return nil unless Gitlab::LDAP::Config.enabled?
  28. Gitlab::LDAP::Authentication.login(login, password)
  29. else
  30. user if user.valid_password?(password)
  31. end
  32. end
  33. def rate_limit!(ip, success:, login:)
  34. rate_limiter = Gitlab::Auth::IpRateLimiter.new(ip)
  35. return unless rate_limiter.enabled?
  36. if success
  37. # Repeated login 'failures' are normal behavior for some Git clients so
  38. # it is important to reset the ban counter once the client has proven
  39. # they are not a 'bad guy'.
  40. rate_limiter.reset!
  41. else
  42. # Register a login failure so that Rack::Attack can block the next
  43. # request from this IP if needed.
  44. rate_limiter.register_fail!
  45. if rate_limiter.banned?
  46. Rails.logger.info "IP #{ip} failed to login " \
  47. "as #{login} but has been temporarily banned from Git auth"
  48. end
  49. end
  50. end
  51. private
  52. def valid_ci_request?(login, password, project)
  53. matched_login = /(?<service>^[a-zA-Z]*-ci)-token$/.match(login)
  54. return false unless project && matched_login.present?
  55. underscored_service = matched_login['service'].underscore
  56. if underscored_service == 'gitlab_ci'
  57. project && project.valid_build_token?(password)
  58. elsif Service.available_services_names.include?(underscored_service)
  59. # We treat underscored_service as a trusted input because it is included
  60. # in the Service.available_services_names whitelist.
  61. service = project.public_send("#{underscored_service}_service")
  62. service && service.activated? && service.valid_token?(password)
  63. end
  64. end
  65. def populate_result(login, password)
  66. result =
  67. user_with_password_for_git(login, password) ||
  68. oauth_access_token_check(login, password) ||
  69. personal_access_token_check(login, password)
  70. if result
  71. result.type = nil unless result.user
  72. if result.user && result.user.two_factor_enabled? && result.type == :gitlab_or_ldap
  73. result.type = :missing_personal_token
  74. end
  75. end
  76. result || Result.new
  77. end
  78. def user_with_password_for_git(login, password)
  79. user = find_with_user_password(login, password)
  80. Result.new(user, :gitlab_or_ldap) if user
  81. end
  82. def oauth_access_token_check(login, password)
  83. if login == "oauth2" && password.present?
  84. token = Doorkeeper::AccessToken.by_token(password)
  85. if token && token.accessible?
  86. user = User.find_by(id: token.resource_owner_id)
  87. Result.new(user, :oauth)
  88. end
  89. end
  90. end
  91. def personal_access_token_check(login, password)
  92. if login && password
  93. user = User.find_by_personal_access_token(password)
  94. validation = User.by_login(login)
  95. Result.new(user, :personal_token) if user == validation
  96. end
  97. end
  98. end
  99. end
  100. end