The structure of the project is like this:
The client accesses the back-end gitlab through Apache (the version of gitlab is 10.4, the simplified Chinese version installed manually from the source code), and Apache is used as the reverse proxy server of gitlab
Apache has a built-in CAS client. Users who are not logged in will be redirected to CAS to log in. After logging in, they will jump to gitlab and bring an http header named remote_user to identify the user.
gitlab needs to receive this header and let the user log in. If the user does not exist in the system, gitlab needs to get the user's information from ldap, create the user, and then let the user log in
Implemented method:
There is no ready-made configuration for gitlab to achieve this requirement. Solutions such as omniauth-http-header are feasible in principle, but in the actual operation process, it is difficult to integrate into gitlab (because the Gemfile needs to be modified)
Therefore, in the process of doing this, I adopted the following method: Refer to the code of omniauth-http-header, implement an omniauth provider by myself, and add it to gitlab (without using the gem package)
First, in the /home/git/gitlab/lib folder, create a new http_header.rb, and modify the attribution of the file to the git user, as follows:
require 'omniauth'
module OmniAuth
module Strategies
class HttpHeader
include OmniAuth::Strategy
option :name, 'http_header'
option :authorization_uri, nil
option :uid_header, 'remote_user'
option :info_headers, {}
option :remote_ip, nil
def request_phase
redirect callback_url
end
def callback_phase
if options.remote_ip && !Array(options.remote_ip).include?(request.ip)
raise ::OmniAuth::Error, "Callback from unauthorized IP #{request.ip}"
end
super
end
uid do
fetch_header options.uid_header
end
info do
options.info_headers.each_with_object({}) do |(attribute, header), info|
info[attribute] = fetch_header header
end
end
private
def fetch_header(header)
print request.env
request.env.fetch "HTTP_#{header.upcase.gsub('-', '_')}"
end
end
end
end
Require and load this file in the omniauth initialization file (/home/git/gitlab/config/initializers/omniauth.rb):
Added require on the first line
require '/home/git/gitlab/lib/http_header.rb'
and the last
Rails.application.config.middleware.use OmniAuth::Builder do
provider :http_header,
uid_header: 'remote_user'
end
The entire file is as follows:
require '/home/git/gitlab/lib/http_header.rb'
if Gitlab::LDAP::Config.enabled?
module OmniAuth::Strategies
Gitlab::LDAP::Config.available_servers.each do |server|
# do not redeclare LDAP
next if server['provider_name'] == 'ldap'
const_set(server['provider_class'], Class.new(LDAP))
end
end
end
OmniAuth.config.full_host = Settings.gitlab['base_url']
OmniAuth.config.allowed_request_methods = [:post]
# In case of auto sign-in, the GET method is used (users don't get to click on a button)
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
OmniAuth.config.before_request_phase do |env|
Gitlab::RequestForgeryProtection.call(env)
end
if Gitlab.config.omniauth.enabled
provider_names = Gitlab.config.omniauth.providers.map(&:name)
require 'omniauth-kerberos' if provider_names.include?('kerberos')
end
module OmniAuth
module Strategies
autoload :Bitbucket, Rails.root.join('lib', 'omni_auth', 'strategies', 'bitbucket')
end
end
Rails.application.config.middleware.use OmniAuth::Builder do
provider :http_header,
uid_header: 'remote_user'
end
3. Configure the provider of ldap and omniauth in the gitlab.yml file, and get the information that is not available from ldap
The relevant configuration is as follows (ldap configuration has nothing to do with the theme and is omitted):
omniauth:
enabled: true
auto_sign_in_with_provider: http_header
auto_link_ldap_user: true
providers:
- { name: 'http_header',
label: 'http_header',
args: {
uid_header: 'remote_user'
} }
4. By default, nginx will remove the underlined header. Therefore, the remote_user is killed when passing through nginx. This command needs to be configured under the server node of nginx:
underscores_in_headers on;
Regarding the issue of single-point exit: let apache intercept the exit address of gitlab and redirect it to the exit address of cas. When cas exits, clear the sessioncookie _gitlab_session set by gitlab to achieve single-point exit