Commit 7b928de0 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'kerberos_ee' into 'master'

Kerberos support

https://dev.gitlab.org/gitlab/gitlabhq/issues/1414

Ability to login using kerberos credentials

![Screen Shot 2014-12-12 at 21.06.01](https://dev.gitlab.org/uploads/gitlab/gitlab-ee/cdc0fb7ee9/Screen_Shot_2014-12-12_at_21.06.01.png)

Ability to attach kerberos account

![Screen Shot 2014-12-12 at 21.19.23](https://dev.gitlab.org/uploads/gitlab/gitlab-ee/e926fb3798/Screen_Shot_2014-12-12_at_21.19.23.png)

See merge request !267
parents c97baeb9 73c0dfd2
...@@ -4,6 +4,7 @@ v 7.6.0 ...@@ -4,6 +4,7 @@ v 7.6.0
- Dont show LDAP groups settings if LDAP disabled - Dont show LDAP groups settings if LDAP disabled
- Rebase on merge request. Introduced merge request option to rebase before merging - Rebase on merge request. Introduced merge request option to rebase before merging
- Better message for failed pushes because of git hooks - Better message for failed pushes because of git hooks
- Kerberos support for web interface and git HTTP
v 7.5.3 v 7.5.3
- Only set up Sidetiq from a Sidekiq server process (fixes Redis::InheritedError) - Only set up Sidetiq from a Sidekiq server process (fixes Redis::InheritedError)
......
...@@ -28,6 +28,7 @@ gem 'omniauth-google-oauth2' ...@@ -28,6 +28,7 @@ gem 'omniauth-google-oauth2'
gem 'omniauth-twitter' gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
gem 'omniauth-shibboleth' gem 'omniauth-shibboleth'
gem 'omniauth-kerberos'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
......
...@@ -323,6 +323,11 @@ GEM ...@@ -323,6 +323,11 @@ GEM
omniauth-google-oauth2 (0.2.5) omniauth-google-oauth2 (0.2.5)
omniauth (> 1.0) omniauth (> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
omniauth-kerberos (0.2.0)
omniauth-multipassword
timfel-krb5-auth (~> 0.8)
omniauth-multipassword (0.4.1)
omniauth (~> 1.0)
omniauth-oauth (1.0.1) omniauth-oauth (1.0.1)
oauth oauth
omniauth (~> 1.0) omniauth (~> 1.0)
...@@ -536,6 +541,7 @@ GEM ...@@ -536,6 +541,7 @@ GEM
thread_safe (0.3.4) thread_safe (0.3.4)
tilt (1.4.1) tilt (1.4.1)
timers (1.1.0) timers (1.1.0)
timfel-krb5-auth (0.8)
tinder (1.9.3) tinder (1.9.3)
eventmachine (~> 1.0) eventmachine (~> 1.0)
faraday (~> 0.8) faraday (~> 0.8)
...@@ -661,6 +667,7 @@ DEPENDENCIES ...@@ -661,6 +667,7 @@ DEPENDENCIES
omniauth (~> 1.1.3) omniauth (~> 1.1.3)
omniauth-github omniauth-github
omniauth-google-oauth2 omniauth-google-oauth2
omniauth-kerberos
omniauth-shibboleth omniauth-shibboleth
omniauth-twitter omniauth-twitter
org-ruby (= 0.9.9) org-ruby (= 0.9.9)
......
class OmniauthCallbacksController < Devise::OmniauthCallbacksController class OmniauthCallbacksController < Devise::OmniauthCallbacksController
protect_from_forgery except: :kerberos
Gitlab.config.omniauth.providers.each do |provider| Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do define_method provider['name'] do
handle_omniauth handle_omniauth
......
...@@ -3,6 +3,14 @@ module OauthHelper ...@@ -3,6 +3,14 @@ module OauthHelper
Gitlab.config.ldap.enabled Gitlab.config.ldap.enabled
end end
def kerberos_enabled?
enabled_oauth_providers.include?(:kerberos)
end
def standard_login_form_only?
ldap_enabled? || kerberos_enabled?
end
def default_providers def default_providers
[:twitter, :github, :google_oauth2, :ldap] [:twitter, :github, :google_oauth2, :ldap]
end end
...@@ -13,11 +21,13 @@ module OauthHelper ...@@ -13,11 +21,13 @@ module OauthHelper
def enabled_social_providers def enabled_social_providers
enabled_oauth_providers.select do |name| enabled_oauth_providers.select do |name|
[:twitter, :github, :google_oauth2].include?(name.to_sym) [:twitter, :github, :google_oauth2, :kerberos].include?(name.to_sym)
end end
end end
def additional_providers def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')} enabled_oauth_providers.reject do |provider|
provider.to_s.starts_with?('ldap') || provider == :kerberos
end
end end
end end
= form_tag(user_omniauth_callback_path(provider), id: 'new_kerberos_user' ) do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "Kerberos Login", autofocus: "autofocus"}
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
%br/
= button_tag "Kerberos Sign in", class: "btn-save btn"
\ No newline at end of file
...@@ -2,18 +2,26 @@ ...@@ -2,18 +2,26 @@
.login-heading .login-heading
%h3 Sign in %h3 Sign in
.login-body .login-body
- if ldap_enabled? - if standard_login_form_only?
%ul.nav.nav-tabs %ul.nav.nav-tabs
- @ldap_servers.each_with_index do |server, i| - if ldap_enabled?
%li{class: (:active if i.zero?)} - @ldap_servers.each_with_index do |server, i|
= link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab' %li{class: (:active if i.zero?)}
= link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
- if kerberos_enabled?
%li{class: (:active unless ldap_enabled?)}
= link_to "Kerberos", "#tab-kerberos", 'data-toggle' => 'tab'
- if gitlab_config.signin_enabled - if gitlab_config.signin_enabled
%li %li
= link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab' = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
.tab-content .tab-content
- @ldap_servers.each_with_index do |server, i| - if ldap_enabled?
%div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)} - @ldap_servers.each_with_index do |server, i|
= render 'devise/sessions/new_ldap', provider: server['provider_name'] %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
= render 'devise/sessions/new_ldap', provider: server['provider_name']
- if kerberos_enabled?
%div#tab-kerberos.tab-pane{class: (:active unless ldap_enabled?)}
= render 'devise/sessions/new_kerberos', provider: :kerberos
- if gitlab_config.signin_enabled - if gitlab_config.signin_enabled
%div#tab-signin.tab-pane %div#tab-signin.tab-pane
= render 'devise/sessions/new_base' = render 'devise/sessions/new_base'
......
...@@ -262,9 +262,9 @@ ActiveRecord::Schema.define(version: 20141205134006) do ...@@ -262,9 +262,9 @@ ActiveRecord::Schema.define(version: 20141205134006) do
t.datetime "updated_at" t.datetime "updated_at"
t.string "type" t.string "type"
t.string "description", default: "", null: false t.string "description", default: "", null: false
t.string "avatar"
t.string "ldap_cn" t.string "ldap_cn"
t.integer "ldap_access" t.integer "ldap_access"
t.string "avatar"
end end
add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
...@@ -325,8 +325,8 @@ ActiveRecord::Schema.define(version: 20141205134006) do ...@@ -325,8 +325,8 @@ ActiveRecord::Schema.define(version: 20141205134006) do
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "import_status" t.string "import_status"
t.float "repository_size", default: 0.0 t.float "repository_size", default: 0.0
t.text "merge_requests_template"
t.integer "star_count", default: 0, null: false t.integer "star_count", default: 0, null: false
t.text "merge_requests_template"
t.boolean "merge_requests_rebase_enabled", default: false t.boolean "merge_requests_rebase_enabled", default: false
end end
......
...@@ -10,6 +10,7 @@ See the documentation below for details on how to configure these services. ...@@ -10,6 +10,7 @@ See the documentation below for details on how to configure these services.
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth. - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth.
- [Jenkins](jenkins.md) Integrate with the Jenkins CI - [Jenkins](jenkins.md) Integrate with the Jenkins CI
- [Slack](slack.md) Integrate with the Slack chat service - [Slack](slack.md) Integrate with the Slack chat service
- [Kerberos](kerberos.md) Integrate with Kerberos
## Project services ## Project services
......
# Kerberos integration
GitLab can be configured to allow your users to sign with their Kerberos credentials.
Kerberos integration can be enabled as a regular omniauth provider, edit [gitlab.rb (omnibus-gitlab)`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#omniauth-google-twitter-github-login) or [gitlab.yml (source installations)](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example) on your GitLab server and restart GitLab. You only need to specify the provider name. For example:
```
{ name: 'kerberos'}
```
You still need to configure your system for Kerberos usage, such as specifying realms. GitLab will make use of the system's Kerberos settings.
The first time a user signs in with Kerberos credentials, GitLab will create a new GitLab user associated with the email, which is built from the kerberos username and realm. Existing GitLab users can go to profile > account and attach a Kerberos account.
## HTTP git access
A linked Kerberos account enables you to `git pull` and `git push` using your Kerberos account, as well as your standard GitLab credentials.
\ No newline at end of file
...@@ -2,6 +2,11 @@ module Gitlab ...@@ -2,6 +2,11 @@ module Gitlab
class Auth class Auth
def find(login, password) def find(login, password)
user = User.by_login(login) user = User.by_login(login)
if Devise.omniauth_providers.include?(:kerberos)
kerberos_user = Gitlab::Kerberos::Authentication.login(login, password)
return kerberos_user if kerberos_user
end
# If no user is found, or it's an LDAP server, try LDAP. # If no user is found, or it's an LDAP server, try LDAP.
# LDAP users are only authenticated via LDAP # LDAP users are only authenticated via LDAP
......
require "krb5_auth"
# This calls helps to authenticate to Kerberos by providing username and password
module Gitlab
module Kerberos
class Authentication
def self.login(login, password)
return unless Devise.omniauth_providers.include?(:kerberos)
return unless login.present? && password.present?
auth = new(login, password)
auth.login
end
def initialize(login, password)
@login = login
@password = password
@krb5 = ::Krb5Auth::Krb5.new
end
def valid?
@krb5.get_init_creds_password(@login, @password)
rescue ::Krb5Auth::Krb5::Exception
false
end
def login
valid? && find_by_login(@login)
end
private
def find_by_login(login)
identity = ::Identity.
where(provider: :kerberos).
where('lower(extern_uid) = ?', login).last
identity && identity.user
end
end
end
end
...@@ -17,4 +17,16 @@ describe OauthHelper do ...@@ -17,4 +17,16 @@ describe OauthHelper do
helper.additional_providers.should == [] helper.additional_providers.should == []
end end
end end
describe "kerberos_enabled?" do
it 'returns true' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github, :kerberos] }
helper.kerberos_enabled?.should be_true
end
it 'returns false' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] }
helper.kerberos_enabled?.should be_false
end
end
end end
\ No newline at end of file
...@@ -35,6 +35,17 @@ describe Gitlab::Auth do ...@@ -35,6 +35,17 @@ describe Gitlab::Auth do
expect( gl_auth.find(username, password) ).to_not eql user expect( gl_auth.find(username, password) ).to_not eql user
end end
context "with kerberos" do
before { Devise.stub(omniauth_providers: [:kerberos]) }
it "finds user" do
Gitlab::Kerberos::Authentication.stub(valid?: true)
Gitlab::Kerberos::Authentication.stub(email: user.email)
expect( gl_auth.find(username, password) ).to eql user
end
end
context "with ldap enabled" do context "with ldap enabled" do
before { Gitlab::LDAP::Config.stub(enabled?: true) } before { Gitlab::LDAP::Config.stub(enabled?: true) }
......
require 'spec_helper'
describe Gitlab::Kerberos::Authentication do
let(:klass) { Gitlab::Kerberos::Authentication }
let(:user) { create(:omniauth_user, provider: :kerberos, extern_uid: 'gitlab') }
let(:login) { 'john' }
let(:password) { 'password' }
describe :login do
before do
Devise.stub(omniauth_providers: [:kerberos])
end
it "finds the user if authentication is successful" do
kerberos_realm = user.email.sub(/.*@/, '')
::Krb5Auth::Krb5.any_instance.stub(get_init_creds_password: true)
::Krb5Auth::Krb5.any_instance.stub(get_default_realm: kerberos_realm)
expect(klass.login('gitlab', password)).to be_true
end
it "returns false if there is no such user in kerberos" do
kerberos_login = "some-login"
kerberos_realm = user.email.sub(/.*@/, '')
::Krb5Auth::Krb5.any_instance.stub(get_init_creds_password: true)
::Krb5Auth::Krb5.any_instance.stub(get_default_realm: kerberos_realm)
expect(klass.login(kerberos_login, password)).to be_false
end
end
end
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment