Merge branch 'tduehr/gitlab-ce-cas-support'

This commit is contained in:
Douwe Maan 2015-12-21 17:38:37 +01:00
commit 9832e60ffb
11 changed files with 144 additions and 1 deletions

View file

@ -70,6 +70,7 @@ v 8.2.3
- Enable devise paranoid mode to prevent user enumeration attack - Enable devise paranoid mode to prevent user enumeration attack
- Webhook payload has an added, modified and removed properties for each commit - Webhook payload has an added, modified and removed properties for each commit
- Fix 500 error when creating a merge request that removes a submodule - Fix 500 error when creating a merge request that removes a submodule
- Add CAS support (tduehr)
v 8.2.2 v 8.2.2
- Fix 404 in redirection after removing a project (Stan Hu) - Fix 404 in redirection after removing a project (Stan Hu)

View file

@ -23,6 +23,7 @@ gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0' gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2' gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-cas3', '~> 1.1.2'
gem 'omniauth-facebook', '~> 3.0.0' gem 'omniauth-facebook', '~> 3.0.0'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-gitlab', '~> 1.0.0'

View file

@ -439,6 +439,10 @@ GEM
multi_json (~> 1.7) multi_json (~> 1.7)
omniauth (~> 1.1) omniauth (~> 1.1)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.0)
omniauth-cas3 (1.1.3)
addressable (~> 2.3)
nokogiri (~> 1.6.6)
omniauth (~> 1.2)
omniauth-facebook (3.0.0) omniauth-facebook (3.0.0)
omniauth-oauth2 (~> 1.2) omniauth-oauth2 (~> 1.2)
omniauth-github (1.1.2) omniauth-github (1.1.2)
@ -893,6 +897,7 @@ DEPENDENCIES
octokit (~> 3.7.0) octokit (~> 3.7.0)
omniauth (~> 1.2.2) omniauth (~> 1.2.2)
omniauth-bitbucket (~> 0.0.2) omniauth-bitbucket (~> 0.0.2)
omniauth-cas3 (~> 1.1.2)
omniauth-facebook (~> 3.0.0) omniauth-facebook (~> 3.0.0)
omniauth-github (~> 1.1.1) omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0) omniauth-gitlab (~> 1.0.0)

View file

@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
before_action :authenticate_user_from_token! before_action :authenticate_user_from_token!
before_action :authenticate_user! before_action :authenticate_user!
before_action :validate_user_service_ticket!
before_action :reject_blocked! before_action :reject_blocked!
before_action :check_password_expiration before_action :check_password_expiration
before_action :ldap_security_check before_action :ldap_security_check
@ -202,6 +203,20 @@ class ApplicationController < ActionController::Base
end end
end end
def validate_user_service_ticket!
return unless signed_in? && session[:service_tickets]
valid = session[:service_tickets].all? do |provider, ticket|
Gitlab::OAuth::Session.valid?(provider, ticket)
end
unless valid
session[:service_tickets] = nil
sign_out current_user
redirect_to new_user_session_path
end
end
def check_password_expiration def check_password_expiration
if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user?
redirect_to new_profile_password_path and return redirect_to new_profile_password_path and return

View file

@ -1,6 +1,6 @@
class OmniauthCallbacksController < Devise::OmniauthCallbacksController class OmniauthCallbacksController < Devise::OmniauthCallbacksController
protect_from_forgery except: [:kerberos, :saml] protect_from_forgery except: [:kerberos, :saml, :cas3]
Gitlab.config.omniauth.providers.each do |provider| Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do define_method provider['name'] do
@ -42,6 +42,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
render 'errors/omniauth_error', layout: "errors", status: 422 render 'errors/omniauth_error', layout: "errors", status: 422
end end
def cas3
ticket = params['ticket']
if ticket
handle_service_ticket oauth['provider'], ticket
end
handle_omniauth
end
private private
def handle_omniauth def handle_omniauth
@ -84,6 +92,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_user_session_path redirect_to new_user_session_path
end end
def handle_service_ticket provider, ticket
Gitlab::OAuth::Session.create provider, ticket
session[:service_tickets] ||= {}
session[:service_tickets][provider] = ticket
end
def oauth def oauth
@oauth ||= request.env['omniauth.auth'] @oauth ||= request.env['omniauth.auth']
end end

View file

@ -287,6 +287,15 @@ production: &base
# arguments, followed by optional 'args' which can be either a hash or an array. # arguments, followed by optional 'args' which can be either a hash or an array.
# Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
providers: providers:
# See omniauth-cas3 for more configuration details
# - { name: 'cas3',
# label: 'cas3',
# args: {
# url: 'https://sso.example.com',
# disable_ssl_verification: false,
# login_url: '/cas/login',
# service_validate_url: '/cas/p3/serviceValidate',
# logout_url: '/cas/logout'} }
# - { name: 'github', # - { name: 'github',
# app_id: 'YOUR_APP_ID', # app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET', # app_secret: 'YOUR_APP_SECRET',
@ -324,6 +333,10 @@ production: &base
# application_name: 'YOUR_APP_NAME', # application_name: 'YOUR_APP_NAME',
# application_password: 'YOUR_APP_PASSWORD' } } # application_password: 'YOUR_APP_PASSWORD' } }
# SSO maximum session duration in seconds. Defaults to CAS default of 8 hours.
# cas3:
# session_duration: 28800
# Shared file storage settings # Shared file storage settings
shared: shared:
# path: /mnt/gitlab # Default: shared # path: /mnt/gitlab # Default: shared

View file

@ -126,6 +126,10 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block
Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil?
Settings.omniauth['providers'] ||= [] Settings.omniauth['providers'] ||= []
Settings.omniauth['cas3'] ||= Settingslogic.new({})
Settings.omniauth.cas3['session_duration'] ||= 8.hours
Settings.omniauth['session_tickets'] ||= Settingslogic.new({})
Settings.omniauth.session_tickets['cas3'] = 'ticket'
Settings['shared'] ||= Settingslogic.new({}) Settings['shared'] ||= Settingslogic.new({})
Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root) Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root)

View file

@ -241,6 +241,16 @@ Devise.setup do |config|
# An Array from the configuration will be expanded. # An Array from the configuration will be expanded.
provider_arguments.concat provider['args'] provider_arguments.concat provider['args']
when Hash when Hash
# Add procs for handling SLO
if provider['name'] == 'cas3'
provider['args'][:on_single_sign_out] = lambda do |request|
ticket = request.params[:session_index]
raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket)
Gitlab::OAuth::Session.destroy(:cas3, ticket)
true
end
end
# A Hash from the configuration will be passed as is. # A Hash from the configuration will be passed as is.
provider_arguments << provider['args'].symbolize_keys provider_arguments << provider['args'].symbolize_keys
end end

View file

@ -9,6 +9,7 @@ See the documentation below for details on how to configure these services.
- [LDAP](ldap.md) Set up sign in via LDAP - [LDAP](ldap.md) Set up sign in via LDAP
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth. - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [Slack](slack.md) Integrate with the Slack chat service - [Slack](slack.md) Integrate with the Slack chat service
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [OAuth2 provider](oauth_provider.md) OAuth2 application creation
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages

62
doc/integration/cas.md Normal file
View file

@ -0,0 +1,62 @@
# CAS OmniAuth Provider
To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab will supply to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
1. On your GitLab server, open the configuration file.
For omnibus package:
```sh
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
```sh
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
For omnibus package:
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "cas3",
label: "cas",
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout'} }
}
}
]
```
For installations from source:
```
- { name: 'cas3',
label: 'cas',
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout'} }
```
1. Change 'CAS_PATH' to the root of your CAS instance (ie. `cas`).
1. If your CAS instance does not use default TGC lifetimes, update the `cas3.session_duration` to at least the current TGC maximum lifetime. To explicitly disable SLO, regardless of CAS settings, set this to 0.
1. Save the configuration file.
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a CAS tab in the sign in form.

View file

@ -0,0 +1,17 @@
module Gitlab
module OAuth
module Session
def self.create(provider, ticket)
Rails.cache.write("gitlab:#{provider}:#{ticket}", ticket, expires_in: Gitlab.config.omniauth.cas3.session_duration)
end
def self.destroy(provider, ticket)
Rails.cache.delete("gitlab:#{provider}:#{ticket}")
end
def self.valid?(provider, ticket)
Rails.cache.read("gitlab:#{provider}:#{ticket}").present?
end
end
end
end