Groundwork for Kerberos SPNEGO (EE feature)
This commit is contained in:
parent
2efee5f641
commit
4bcad1cbdd
|
@ -1,4 +1,9 @@
|
|||
# This file should be identical in GitLab Community Edition and Enterprise Edition
|
||||
|
||||
class Projects::GitHttpController < Projects::ApplicationController
|
||||
include ActionController::HttpAuthentication::Basic
|
||||
include KerberosSpnegoHelper
|
||||
|
||||
attr_reader :user
|
||||
|
||||
# Git clients will not know what authenticity token to send along
|
||||
|
@ -40,9 +45,12 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def authenticate_user
|
||||
return if project && project.public? && upload_pack?
|
||||
if project && project.public? && upload_pack?
|
||||
return # Allow access
|
||||
end
|
||||
|
||||
authenticate_or_request_with_http_basic do |login, password|
|
||||
if allow_basic_auth? && basic_auth_provided?
|
||||
login, password = user_name_and_password(request)
|
||||
auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
|
||||
|
||||
if auth_result.type == :ci && upload_pack?
|
||||
|
@ -53,8 +61,31 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
@user = auth_result.user
|
||||
end
|
||||
|
||||
ci? || user
|
||||
if ci? || user
|
||||
return # Allow access
|
||||
end
|
||||
elsif allow_kerberos_spnego_auth? && spnego_provided?
|
||||
@user = find_kerberos_user
|
||||
|
||||
if user
|
||||
send_final_spnego_response
|
||||
return # Allow access
|
||||
end
|
||||
end
|
||||
|
||||
send_challenges
|
||||
render plain: "HTTP Basic: Access denied\n", status: 401
|
||||
end
|
||||
|
||||
def basic_auth_provided?
|
||||
has_basic_credentials?(request)
|
||||
end
|
||||
|
||||
def send_challenges
|
||||
challenges = []
|
||||
challenges << 'Basic realm="GitLab"' if allow_basic_auth?
|
||||
challenges << spnego_challenge if allow_kerberos_spnego_auth?
|
||||
headers['Www-Authenticate'] = challenges.join("\n") if challenges.any?
|
||||
end
|
||||
|
||||
def ensure_project_found!
|
||||
|
@ -120,7 +151,7 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def render_not_found
|
||||
render text: 'Not Found', status: :not_found
|
||||
render plain: 'Not Found', status: :not_found
|
||||
end
|
||||
|
||||
def ci?
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
module KerberosSpnegoHelper
|
||||
def allow_basic_auth?
|
||||
true # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
|
||||
def allow_kerberos_spnego_auth?
|
||||
false # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
end
|
|
@ -350,23 +350,23 @@ describe 'Git HTTP requests', lib: true do
|
|||
end
|
||||
|
||||
def clone_get(project, options={})
|
||||
get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password))
|
||||
get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token))
|
||||
end
|
||||
|
||||
def clone_post(project, options={})
|
||||
post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password))
|
||||
post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token))
|
||||
end
|
||||
|
||||
def push_get(project, options={})
|
||||
get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password))
|
||||
get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token))
|
||||
end
|
||||
|
||||
def push_post(project, options={})
|
||||
post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password))
|
||||
post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token))
|
||||
end
|
||||
|
||||
def download(project, user: nil, password: nil)
|
||||
args = [project, { user: user, password: password }]
|
||||
def download(project, user: nil, password: nil, spnego_request_token: nil)
|
||||
args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }]
|
||||
|
||||
clone_get(*args)
|
||||
yield response
|
||||
|
@ -375,8 +375,8 @@ describe 'Git HTTP requests', lib: true do
|
|||
yield response
|
||||
end
|
||||
|
||||
def upload(project, user: nil, password: nil)
|
||||
args = [project, { user: user, password: password }]
|
||||
def upload(project, user: nil, password: nil, spnego_request_token: nil)
|
||||
args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }]
|
||||
|
||||
push_get(*args)
|
||||
yield response
|
||||
|
@ -385,11 +385,14 @@ describe 'Git HTTP requests', lib: true do
|
|||
yield response
|
||||
end
|
||||
|
||||
def auth_env(user, password)
|
||||
def auth_env(user, password, spnego_request_token)
|
||||
env = {}
|
||||
if user && password
|
||||
{ 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password) }
|
||||
else
|
||||
{}
|
||||
env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password)
|
||||
elsif spnego_request_token
|
||||
env['HTTP_AUTHORIZATION'] = "Negotiate #{::Base64.strict_encode64('opaque_request_token')}"
|
||||
end
|
||||
|
||||
env
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue