Commit 635517a3 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ee into ce_upstream

parents 79642037 ceb2af7c
......@@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.9.0 (unreleased)
- Fix nil user handling in UpdateMirrorService
- Allow LDAP to mark users as external based on their group membership. !432
v 8.8.3
- Add standard web hook headers to Jenkins CI post. !374
......
......@@ -351,6 +351,12 @@ production: &base
#
admin_group: ''
# LDAP group of users who should be marked as external users in GitLab
#
# Ex. ['Contractors', 'Interns']
#
external_groups: []
# Name of attribute which holds a ssh public key of the user object.
# If false or nil, SSH key syncronisation will be disabled.
#
......
......@@ -157,6 +157,7 @@ if Settings.ldap['enabled'] || Rails.env.test?
server['attributes'] = {} if server['attributes'].nil?
server['provider_name'] ||= "ldap#{key}".downcase
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
server['external_groups'] = [] if server['external_groups'].nil?
Settings.ldap['servers'][key] = server
end
end
......
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160530150109) do
ActiveRecord::Schema.define(version: 20160530214349) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "pg_trgm"
......
......@@ -146,6 +146,14 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
#
admin_group: ''
# An array of CNs of groups containing users that should be considered external
#
# Ex. ['interns', 'contractors']
#
# Note: Not `cn=interns` or the full DN
#
external_groups: []
# The LDAP attribute containing a user's public SSH key
#
# Ex. ssh_public_key
......@@ -184,6 +192,28 @@ production:
# snip...
```
### External Groups
>**Note:** External Groups configuration is only available in GitLab EE Version
8.9 and above.
Using the `external_groups` setting will allow you to mark all users belonging
to these groups as [external users](../../permissions/). Group membership is
checked periodically through the `LdapGroupSync` background task.
**Configuration**
```yaml
# An array of CNs of groups containing users that should be considered external
#
# Ex. ['interns', 'contractors']
#
# Note: Not `cn=interns` or the full DN
#
external_groups: []
```
## Using an LDAP filter to limit access to your GitLab server
If you want to limit all GitLab access to a subset of the LDAP users on your
......
......@@ -101,6 +101,10 @@ module Gitlab
options['timeout'].to_i
end
def external_groups
options['external_groups']
end
protected
def base_config
......
......@@ -49,6 +49,14 @@ module Gitlab
logger.debug { "No `admin_group` configured for '#{provider}' provider. Skipping" }
end
if external_groups.empty?
logger.debug { "No `external_groups` configured for '#{provider}' provider. Skipping" }
else
logger.debug { "Syncing external users for '#{provider}' provider" }
sync_external_users
logger.debug { "Finished syncing external users for '#{provider}' provider" }
end
nil
end
......@@ -121,6 +129,36 @@ module Gitlab
end
end
# Update external users based on the specified external groups CN
def sync_external_users
current_external_users = ::User.external.with_provider(provider)
verified_external_users = []
external_groups.each do |group|
group_dns = dns_for_group_cn(group)
group_dns.each do |member_dn|
user = Gitlab::LDAP::User.find_by_uid_and_provider(member_dn, provider)
if user.present?
user.external = true
user.save
verified_external_users << user
else
logger.debug do
<<-MSG.strip_heredoc.tr("\n", ' ')
#{self.class.name}: User with DN `#{member_dn}` should be marked as
external but there is no user in GitLab with that identity.
Membership will be updated once the user signs in for the first time.
MSG
end
end
end
end
update_external_permissions(current_external_users, verified_external_users)
end
private
# Cache LDAP group member DNs so we don't query LDAP groups more than once.
......@@ -151,6 +189,10 @@ module Gitlab
config.admin_group
end
def external_groups
config.external_groups
end
def ldap_group_member_dns(ldap_group_cn)
ldap_group = Gitlab::LDAP::Group.find_by_cn(ldap_group_cn, adapter)
unless ldap_group.present?
......@@ -277,6 +319,16 @@ module Gitlab
end
end
def update_external_permissions(users, verified)
# Restore normal access to users no longer found in the external groups
users.each do |user|
unless verified.include?(user)
user.external = false
user.save
end
end
end
def add_new_members(group, access_levels)
logger.debug { "Adding new members to '#{group.name}' group" }
......
This diff is collapsed.
require 'spec_helper'
describe Projects::UpdateMirrorService do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:mirror_user) { project.owner }
subject { described_class.new(project, mirror_user) }
before do
project.import_url = Project::UNKNOWN_IMPORT_URL
project.mirror = true
project.mirror_user = mirror_user
project.save
end
let(:project) { create(:project, :mirror, import_url: Project::UNKNOWN_IMPORT_URL) }
describe "#execute" do
it "fetches the upstream repository" do
expect(project).to receive(:fetch_mirror)
subject.execute
described_class.new(project, project.owner).execute
end
it "succeeds" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
result = subject.execute
result = described_class.new(project, project.owner).execute
expect(result[:status]).to eq(:success)
end
describe "updating tags" do
it "creates new tags" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
subject.execute
described_class.new(project, project.owner).execute
expect(repository.tag_names).to include('new-tag')
expect(project.repository.tag_names).to include('new-tag')
end
end
describe "updating branches" do
it "creates new branches" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
subject.execute
described_class.new(project, project.owner).execute
expect(repository.branch_names).to include('new-branch')
expect(project.repository.branch_names).to include('new-branch')
end
it "updates existing branches" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
subject.execute
described_class.new(project, project.owner).execute
expect(repository.find_branch('existing-branch').target).to eq(repository.find_branch('master').target)
expect(project.repository.find_branch('existing-branch').target)
.to eq(project.repository.find_branch('master').target)
end
it "doesn't update diverged branches" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
subject.execute
described_class.new(project, project.owner).execute
expect(repository.find_branch('markdown').target).not_to eq(repository.find_branch('master').target)
expect(project.repository.find_branch('markdown').target)
.not_to eq(project.repository.find_branch('master').target)
end
end
describe "when the mirror user doesn't have access" do
let(:mirror_user) { create(:user) }
it "fails" do
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
stub_fetch_mirror(project)
result = subject.execute
result = described_class.new(project, build_stubbed(:user)).execute
expect(result[:status]).to eq(:error)
end
end
describe "when no user is present" do
let(:mirror_user) { }
it "fails" do
result = subject.execute
result = described_class.new(project, nil).execute
expect(result[:status]).to eq(:error)
end
end
end
def stub_fetch_mirror(project, repository: project.repository)
allow(project).to receive(:fetch_mirror) { fetch_mirror(repository) }
end
def fetch_mirror(repository)
rugged = repository.rugged
masterrev = repository.find_branch('master').target
......
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