项目的结构是这样的:

客户端通过Apache来访问后端的gitlab(gitlab的版本是10.4,手动从源码安装的简体中文版) , Apache作为gitlab的反向代理服务器

Apache内置了CAS的客户端,未登录的用户会重定向到CAS去登录,登录之后,跳转到gitlab,带上一个名为 remote_user的http header 来标识用户的身份

gitlab需要接收这个header,并让用户登录,若系统中不存在该用户,gitlab要从ldap中拿到用户的信息,创建用户,然后让用户登录

实现的方法:

gitlab没有现成的配置来实现这个需求, omniauth-http-header等方案,原理上是可行的,但是在实际操作过程中,很难集成到gitlab中去(因为要修改Gemfile)

所以,我在做的过程中,采用了如下的方法: 参考 omniauth-http-header的代码,自己实现一个 omniauth的provider,添加到gitlab中去(不使用gem包的方式)

首先,在/home/git/gitlab/lib文件夹下,新建http_header.rb,并修改文件的归属为git用户,内容如下:

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

在omniauth的初始化文件(/home/git/gitlab/config/initializers/omniauth.rb)里require和加载这个文件:

增加了首行的require

require '/home/git/gitlab/lib/http_header.rb'

和最后的

Rails.application.config.middleware.use OmniAuth::Builder do
	    provider :http_header,
	    uid_header: 'remote_user'	
end

整个文件如下:

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.在gitlab.yml文件里配置ldap和omniauth的provider,没有的信息从ldap中拿到

相关配置如下(ldap配置和主题无关,被省略了):

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.nginx默认是会去掉带下划线的header,所以,remote_user在经过nginx的时候被干掉了,需要在nginx的server结点下配置这个指令:

underscores_in_headers on;

关于单点退出的问题:让apache拦截gitlab的退出地址,重定向到cas的退出地址上,在cas退出的时候,清除掉gitlab设置的sessioncookie _gitlab_session即可实现单点退出

posted on 2018-05-03 23:01  梦中彩虹  阅读(1106)  评论(0编辑  收藏  举报