Commit a1b17f13 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Gitlab Geo force authentication with primary node

parent 5ab12ad0
...@@ -4,6 +4,7 @@ class SessionsController < Devise::SessionsController ...@@ -4,6 +4,7 @@ class SessionsController < Devise::SessionsController
prepend_before_action :authenticate_with_two_factor, only: [:create] prepend_before_action :authenticate_with_two_factor, only: [:create]
prepend_before_action :store_redirect_path, only: [:new] prepend_before_action :store_redirect_path, only: [:new]
prepend_before_action :gitlab_geo_auth, only: [:new]
before_action :auto_sign_in_with_provider, only: [:new] before_action :auto_sign_in_with_provider, only: [:new]
before_action :load_recaptcha before_action :load_recaptcha
...@@ -52,6 +53,8 @@ class SessionsController < Devise::SessionsController ...@@ -52,6 +53,8 @@ class SessionsController < Devise::SessionsController
else else
request.fullpath request.fullpath
end end
elsif session[:geo_redirect].present? && (params['redirect_to_referer'] == 'yes')
stored_location_for(:geo_redirect)
else else
request.fullpath request.fullpath
end end
...@@ -85,6 +88,16 @@ class SessionsController < Devise::SessionsController ...@@ -85,6 +88,16 @@ class SessionsController < Devise::SessionsController
end end
end end
def gitlab_geo_auth
if !signed_in? && Gitlab::Geo.enabled? && Gitlab::Geo.readonly?
# reuse location from :store_redirect_path to share with primary node by shared session
store_location_for(:geo_redirect, stored_location_for(:redirect))
login_uri = URI.join(Gitlab::Geo.primary_node.uri, new_session_path(:user, redirect_to_referer: 'yes'))
redirect_to login_uri.to_s
end
end
def auto_sign_in_with_provider def auto_sign_in_with_provider
provider = Gitlab.config.omniauth.auto_sign_in_with_provider provider = Gitlab.config.omniauth.auto_sign_in_with_provider
return unless provider.present? return unless provider.present?
......
...@@ -3,15 +3,24 @@ ...@@ -3,15 +3,24 @@
# Table name: geo_nodes # Table name: geo_nodes
# #
# id :integer not null, primary key # id :integer not null, primary key
# schema :string
# host :string # host :string
# port :integer
# relative_url_root :string # relative_url_root :string
# primary :boolean # primary :boolean
# #
class GeoNode < ActiveRecord::Base class GeoNode < ActiveRecord::Base
default_value_for :primary, false default_value_for :schema, 'http'
default_value_for :port, 80
default_value_for :relative_url_root, '' default_value_for :relative_url_root, ''
default_value_for :primary, false
validates :host, hostname: true, presence: true, uniqueness: { case_sensitive: false } validates :host, host: true, presence: true, uniqueness: { case_sensitive: false, scope: :port }
validates :primary, uniqueness: { message: 'primary node already exists' }, if: :primary validates :primary, uniqueness: { message: 'primary node already exists' }, if: :primary
validates :schema, inclusion: %w(http https)
def uri
URI.parse("#{schema}://#{host}:#{port}/#{relative_url_root}")
end
end end
# HostnameValidator # HostnameValidator
# #
# Custom validator for Hostnames. # Custom validator for Hosts.
# #
# This is similar to an URI validator, but will make sure no schema or # This is similar to an URI validator, but will make sure no schema or
# path is present, only the domain part. # path is present, only the domain part.
# #
class HostnameValidator < ActiveModel::EachValidator class HostValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
unless valid_hostname?(value) unless valid_host?(value)
record.errors.add(attribute, 'must be a valid host') record.errors.add(attribute, 'must be a valid hostname!')
end end
end end
private private
def valid_hostname?(value) def valid_host?(value)
URI.parse("fake://#{value}").hostname == value URI.parse("http://#{value}").host == value
rescue URI::InvalidURIError => e
false
end end
end end
class CreateGeoNodes < ActiveRecord::Migration class CreateGeoNodes < ActiveRecord::Migration
def change def change
create_table :geo_nodes do |t| create_table :geo_nodes do |t|
t.string :host t.string :schema
t.string :host, index: true
t.integer :port
t.string :relative_url_root t.string :relative_url_root
t.boolean :primary t.boolean :primary, index: true
end end
end end
end end
...@@ -401,11 +401,15 @@ ActiveRecord::Schema.define(version: 20160119170055) do ...@@ -401,11 +401,15 @@ ActiveRecord::Schema.define(version: 20160119170055) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "geo_nodes", force: :cascade do |t| create_table "geo_nodes", force: :cascade do |t|
t.string "schema"
t.string "host" t.string "host"
t.integer "port"
t.string "relative_url_root" t.string "relative_url_root"
t.boolean "primary" t.boolean "primary"
end end
add_index "geo_nodes", ["host"], name: "index_geo_nodes_on_host", using: :btree
add_index "geo_nodes", ["primary"], name: "index_geo_nodes_on_primary", using: :btree
create_table "git_hooks", force: :cascade do |t| create_table "git_hooks", force: :cascade do |t|
t.string "force_push_regex" t.string "force_push_regex"
t.string "delete_branch_regex" t.string "delete_branch_regex"
......
module Gitlab module Gitlab
module Geo module Geo
def self.current_node
GeoNode.find_by(host: Gitlab.config.gitlab.host,
port: Gitlab.config.gitlab.port,
relative_url_root: Gitlab.config.gitlab.relative_url_root)
end
def self.primary_node
GeoNode.find_by(primary: true)
end
def self.enabled? def self.enabled?
GeoNode.exists? GeoNode.exists?
end end
def self.current_node def self.readonly?
GeoNode.find_by(host: Gitlab.config.gitlab.host, relative_url_root: Gitlab.config.gitlab.relative_url_root) self.enabled? && !self.current_node.primary?
end end
end end
end end
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