mooset 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/sample +10 -3
- data/lib/mooset/application.rb +44 -17
- data/lib/mooset/endpoints/endpoint.rb +22 -9
- data/lib/mooset/endpoints/findable.rb +62 -0
- data/lib/mooset/endpoints/gitlab/group.rb +9 -3
- data/lib/mooset/endpoints/gitlab/group_search.rb +25 -22
- data/lib/mooset/endpoints/gitlab/paginate.rb +18 -0
- data/lib/mooset/endpoints/gitlab/user.rb +17 -3
- data/lib/mooset/endpoints/gitlab/user_search.rb +41 -21
- data/lib/mooset/endpoints/gitlab.rb +4 -8
- data/lib/mooset/endpoints/ldap/group.rb +9 -11
- data/lib/mooset/endpoints/ldap/ldap_search.rb +56 -0
- data/lib/mooset/endpoints/ldap/ou.rb +12 -0
- data/lib/mooset/endpoints/ldap/user.rb +8 -13
- data/lib/mooset/endpoints/ldap.rb +6 -18
- data/lib/mooset/endpoints/null.rb +46 -4
- data/lib/mooset/endpoints.rb +4 -3
- data/lib/mooset/resource.rb +18 -4
- data/lib/mooset/synchronize_group.rb +35 -0
- data/lib/mooset/version.rb +1 -1
- data/lib/mooset.rb +1 -2
- metadata +7 -9
- data/lib/mooset/endpoints/console_logger.rb +0 -10
- data/lib/mooset/endpoints/ldap/group_search.rb +0 -31
- data/lib/mooset/endpoints/ldap/user_search.rb +0 -31
- data/lib/mooset/storage.rb +0 -6
- data/lib/mooset/synchronize_users.rb +0 -9
- data/spec/mooset/endpoints/gitlab_spec.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 006161edeef876748ef7483011278a0a26f4098d
|
4
|
+
data.tar.gz: d93d1a0d851946612246a14b03e694a8743ed29c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7077ad440a847771fe16c8b3086b7c0e8d2a5dfff7d464ec96cb7b44279fc94ffc8fec43cf28e559bb127b659ec5cc1561db8a14470086f6824023ba59ea4fc9
|
7
|
+
data.tar.gz: e69db56d141bf63fbcdfe8c77df1b1cae798e67e9088104d4b6d3786c373456251558238a9ecd8e4d2de571dc7e8b0c2b3aa1dcb8e0f77b8484d6b7bfe59afa5
|
data/config/sample
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# vi:syntax=ruby
|
2
2
|
|
3
|
-
define :origin, :
|
3
|
+
define :origin, :ldap, {
|
4
4
|
host: 'localhost',
|
5
5
|
port: 389,
|
6
6
|
bind_dn: 'CN=user,OU=users,DC=domain,DC=com',
|
@@ -8,11 +8,18 @@ define :origin, :null, {
|
|
8
8
|
treebase: 'DC=domain,DC=com'
|
9
9
|
}
|
10
10
|
|
11
|
+
define :ldap_encrypted, :ldap, {
|
12
|
+
host: 'localhost',
|
13
|
+
port: 636,
|
14
|
+
bind_dn: 'CN=user,OU=users,DC=domain,DC=com',
|
15
|
+
bind_password: '',
|
16
|
+
treebase: 'DC=domain,DC=com',
|
17
|
+
encryption: :simple_tls
|
18
|
+
}
|
19
|
+
|
11
20
|
define :gitlab_dev, :gitlab, {
|
12
21
|
endpoint: 'http://gitlab',
|
13
22
|
private_token: ''
|
14
23
|
}
|
15
24
|
|
16
|
-
define :out, :console_logger
|
17
|
-
|
18
25
|
synchronize_users from: :origin, to: :output, query: '(&(memberof=CN=Users,DC=domain,DC=com)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2)))'
|
data/lib/mooset/application.rb
CHANGED
@@ -1,37 +1,54 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'irb'
|
3
|
+
require 'logger'
|
2
4
|
|
3
5
|
module Mooset
|
4
6
|
class Application
|
5
|
-
attr_accessor :config_filename
|
7
|
+
attr_accessor :config_filename, :interactive, :logfile
|
6
8
|
|
7
|
-
def define(endpoint_name, factory,
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def define(endpoint_name, factory, opts = {})
|
10
|
+
opts[:endpoint_name] = endpoint_name
|
11
|
+
opts[:logger] = logger
|
12
|
+
|
13
|
+
endpoints[endpoint_name] = Mooset::Endpoints::Endpoint.create(factory, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def endpoints
|
17
|
+
@endpoints ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger
|
21
|
+
@logger ||= begin
|
22
|
+
l = ::Logger.new(logfile || STDOUT)
|
23
|
+
l.level = ::Logger::WARN
|
24
|
+
l
|
25
|
+
end
|
11
26
|
end
|
12
27
|
|
13
28
|
def instances
|
14
29
|
@instances ||= {}
|
15
30
|
end
|
16
31
|
|
17
|
-
def
|
18
|
-
|
32
|
+
def synchronize_group(from:, to:, **opts)
|
33
|
+
operations << Mooset::SynchronizeGroups.new(endpoints[from], endpoints[to], opts)
|
19
34
|
end
|
20
35
|
|
21
|
-
def
|
22
|
-
@
|
36
|
+
def operations
|
37
|
+
@operations ||= []
|
23
38
|
end
|
24
39
|
|
25
40
|
def run!
|
26
|
-
|
27
|
-
|
28
|
-
to = instances[event[:to]]
|
29
|
-
opts = event[:opts]
|
30
|
-
|
31
|
-
Mooset::SynchronizeUsers.call(from, to, opts)
|
41
|
+
operations.each do |operation|
|
42
|
+
operation.call
|
32
43
|
end
|
33
44
|
end
|
34
45
|
|
46
|
+
def start_irb
|
47
|
+
$app = self
|
48
|
+
|
49
|
+
IRB.start
|
50
|
+
end
|
51
|
+
|
35
52
|
def read_config
|
36
53
|
instance_eval File.read(config_filename), config_filename
|
37
54
|
end
|
@@ -45,12 +62,22 @@ module Mooset
|
|
45
62
|
|
46
63
|
OptionParser.new do |opts|
|
47
64
|
opts.banner = "Usage: #{$0} [options]"
|
65
|
+
opts.on("-f", "--logfile FILE", "Logfile", s.method(:logfile=))
|
66
|
+
opts.on("-v", "--verbose", "Verbose") do |x|
|
67
|
+
s.logger.level = ::Logger::INFO
|
68
|
+
end
|
69
|
+
|
48
70
|
opts.on("-c", "--config FILE", "Config file", s.method(:config_filename=))
|
71
|
+
opts.on("-i", "--interactive", "Run in interactive mode", s.method(:interactive=))
|
49
72
|
opts.parse!(argv)
|
50
73
|
end
|
51
74
|
|
52
|
-
s.
|
53
|
-
|
75
|
+
if s.config_filename
|
76
|
+
s.read_config
|
77
|
+
s.run! unless s.interactive
|
78
|
+
end
|
79
|
+
|
80
|
+
s.start_irb if s.interactive
|
54
81
|
end
|
55
82
|
|
56
83
|
end
|
@@ -5,13 +5,8 @@ module Mooset
|
|
5
5
|
class Endpoint
|
6
6
|
include Virtus.model
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(endpoint_name, *args)
|
11
|
-
@endpoint_name = endpoint_name
|
12
|
-
|
13
|
-
super(*args)
|
14
|
-
end
|
8
|
+
attribute :logger
|
9
|
+
attribute :endpoint_name
|
15
10
|
|
16
11
|
def self.inherited(klass)
|
17
12
|
super
|
@@ -32,8 +27,26 @@ module Mooset
|
|
32
27
|
downcase
|
33
28
|
end
|
34
29
|
|
35
|
-
def self.create(name,
|
36
|
-
descendants[name].new(
|
30
|
+
def self.create(name, opts = {})
|
31
|
+
descendants[name].new(opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.resources
|
35
|
+
@resources ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.resource(name, &block)
|
39
|
+
resources << name
|
40
|
+
|
41
|
+
define_method(name) do
|
42
|
+
r = instance_variable_get("@#{name}")
|
43
|
+
if r.nil?
|
44
|
+
r = instance_eval(&block)
|
45
|
+
instance_variable_set("@#{name}", r)
|
46
|
+
end
|
47
|
+
r
|
48
|
+
end
|
49
|
+
|
37
50
|
end
|
38
51
|
end
|
39
52
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Mooset
|
2
|
+
module Endpoints
|
3
|
+
module Findable
|
4
|
+
module ClassMethods
|
5
|
+
def import(name, &block)
|
6
|
+
define_method(import_method_name(name), &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def finder(name, &block)
|
10
|
+
define_method(finder_method_name(name), &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def finder_method_name(name)
|
14
|
+
"find_by_#{name}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def import_method_name(name)
|
18
|
+
"import_from_#{name}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module InstanceMethods
|
23
|
+
def import(object)
|
24
|
+
method = self.class.import_method_name(object.provider)
|
25
|
+
|
26
|
+
public_send(method, object)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_from_object(object, *args)
|
30
|
+
finder = object.finders.find { |x| respond_to? self.class.finder_method_name(x) }
|
31
|
+
|
32
|
+
if finder && object[finder]
|
33
|
+
public_send(self.class.finder_method_name(finder), object[finder], *args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_from_hash(hash)
|
38
|
+
key, value = hash.find { |(k, _)| respond_to? self.class.finder_method_name(k) }
|
39
|
+
|
40
|
+
args = hash.tap do |h|
|
41
|
+
h.delete(key)
|
42
|
+
end
|
43
|
+
|
44
|
+
if key && value
|
45
|
+
public_send(self.class.finder_method_name(key), value, args)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find(opts, *args)
|
50
|
+
return find_from_hash(opts, *args) if opts.is_a? Hash
|
51
|
+
|
52
|
+
find_from_object(opts, args)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.included(receiver)
|
57
|
+
receiver.extend ClassMethods
|
58
|
+
receiver.send :include, InstanceMethods
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -8,14 +8,18 @@ module Mooset
|
|
8
8
|
MASTER = 40
|
9
9
|
OWNER = 50
|
10
10
|
|
11
|
+
attribute :gitlab_id
|
11
12
|
attribute :path
|
12
13
|
attribute :owner_id
|
13
14
|
attribute :provider, String, default: "gitlab"
|
14
15
|
|
15
|
-
|
16
|
+
finders [:gitlab_id, :name]
|
17
|
+
|
18
|
+
def self.build(endpoint, group)
|
16
19
|
new(
|
17
|
-
|
20
|
+
endpoint: endpoint,
|
18
21
|
id: group.id,
|
22
|
+
gitlab_id: group.id,
|
19
23
|
name: group.name,
|
20
24
|
path: group.path,
|
21
25
|
owner_id: group.owner_id
|
@@ -23,10 +27,12 @@ module Mooset
|
|
23
27
|
end
|
24
28
|
|
25
29
|
def members
|
26
|
-
endpoint.users.
|
30
|
+
@members ||= endpoint.users.group_members(id).to_a
|
27
31
|
end
|
28
32
|
|
29
33
|
def <<(user)
|
34
|
+
@logger.info "add_group_member #{id} #{user.id} DEVELOPER"
|
35
|
+
|
30
36
|
endpoint.groups.add_group_member(id, user.id, DEVELOPER)
|
31
37
|
end
|
32
38
|
end
|
@@ -2,6 +2,9 @@ module Mooset
|
|
2
2
|
module Endpoints
|
3
3
|
class Gitlab
|
4
4
|
class GroupSearch
|
5
|
+
include Paginate
|
6
|
+
include Findable
|
7
|
+
|
5
8
|
attr_reader :endpoint
|
6
9
|
|
7
10
|
def initialize(endpoint)
|
@@ -9,39 +12,39 @@ module Mooset
|
|
9
12
|
end
|
10
13
|
|
11
14
|
def all
|
12
|
-
|
13
|
-
objects = []
|
15
|
+
return to_enum(:all) unless block_given?
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
page += 1
|
18
|
-
end
|
17
|
+
paginate ->(page){ connection.groups(page: page) }, ->(object){ yield Group.build(endpoint, object) }
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
20
|
+
finder :all do |_, opts = {}|
|
21
|
+
all
|
23
22
|
end
|
24
23
|
|
25
|
-
|
26
|
-
Group.build(endpoint
|
24
|
+
finder :id do |id, opts = {}|
|
25
|
+
Group.build(endpoint, connection.group(id))
|
27
26
|
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
finder :gitlab_id do |gitlab_id, opts = {}|
|
29
|
+
find(id: gitlab_id)
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
finder :name do |name, opts = {}|
|
33
|
+
all.find { |x| x.name == name }
|
34
|
+
end
|
35
|
+
|
36
|
+
import :ldap do |group, opts = {}|
|
37
|
+
create(group.name, group.name.gsub(/( )/, '_').downcase)
|
38
|
+
end
|
39
|
+
|
40
|
+
def members(id)
|
41
|
+
return to_enum(:members, id) unless block_given?
|
37
42
|
|
38
|
-
|
39
|
-
User.build(endpoint.endpoint_name, object)
|
40
|
-
end
|
43
|
+
paginate ->(page){ connection.group_members(id, page: page) }, ->(object){ yield User.build(endpoint, object) }
|
41
44
|
end
|
42
45
|
|
43
46
|
def create(name, path)
|
44
|
-
Group.build(endpoint
|
47
|
+
Group.build(endpoint, connection.create_group(name, path))
|
45
48
|
end
|
46
49
|
|
47
50
|
def add_group_member(team_id, user_id, access_level = 50)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Mooset
|
2
|
+
module Endpoints
|
3
|
+
class Gitlab
|
4
|
+
module Paginate
|
5
|
+
def paginate(lookup, builder)
|
6
|
+
page = 1
|
7
|
+
|
8
|
+
while (o = lookup.call(page)).length > 0 do
|
9
|
+
o.each do |oo|
|
10
|
+
builder.call(oo)
|
11
|
+
end
|
12
|
+
page += 1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -2,21 +2,35 @@ module Mooset
|
|
2
2
|
module Endpoints
|
3
3
|
class Gitlab
|
4
4
|
class User < Models::User
|
5
|
+
attribute :gitlab_id
|
5
6
|
attribute :state
|
6
7
|
attribute :access_level
|
7
8
|
attribute :provider, String, default: "gitlab"
|
9
|
+
attribute :ldap_id, String
|
8
10
|
|
9
|
-
|
11
|
+
finders [:gitlab_id, :ldap_id, :email, :username]
|
12
|
+
|
13
|
+
def self.build(endpoint, user)
|
10
14
|
self.new(
|
11
|
-
|
15
|
+
endpoint: endpoint,
|
12
16
|
id: user.id,
|
17
|
+
gitlab_id: user.id,
|
13
18
|
username: user.username,
|
14
19
|
full_name: user.name,
|
15
20
|
state: user.state,
|
16
21
|
email: user.email,
|
17
|
-
access_level: user.access_level
|
22
|
+
access_level: user.access_level,
|
23
|
+
ldap_id: Optional.new(user).identities.within do |identities|
|
24
|
+
identity_from(Many.new(identities)).values.first
|
25
|
+
end.value,
|
18
26
|
)
|
19
27
|
end
|
28
|
+
|
29
|
+
def self.identity_from(identities)
|
30
|
+
identities.within do |o|
|
31
|
+
o["extern_uid"] if o["provider"] == 'ldap'
|
32
|
+
end
|
33
|
+
end
|
20
34
|
end
|
21
35
|
end
|
22
36
|
end
|
@@ -2,6 +2,9 @@ module Mooset
|
|
2
2
|
module Endpoints
|
3
3
|
class Gitlab
|
4
4
|
class UserSearch
|
5
|
+
include Paginate
|
6
|
+
include Findable
|
7
|
+
|
5
8
|
attr_reader :endpoint
|
6
9
|
|
7
10
|
def initialize(endpoint)
|
@@ -9,35 +12,52 @@ module Mooset
|
|
9
12
|
end
|
10
13
|
|
11
14
|
def all
|
12
|
-
|
13
|
-
|
15
|
+
return to_enum(:all) unless block_given?
|
16
|
+
|
17
|
+
paginate ->(page){ connection.users(page: page) }, ->(object){ yield User.build(endpoint, object) }
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
20
|
+
def alll
|
21
|
+
@alll ||= all.to_a
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
24
|
+
finder :id do |id, opts = {}|
|
25
|
+
User.build(endpoint, connection.user(id))
|
23
26
|
end
|
24
27
|
|
25
|
-
|
26
|
-
|
28
|
+
finder :gitlab_id do |gitlab_id, opts = {}|
|
29
|
+
find(id: gitlab_id)
|
27
30
|
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
finder :username do |username, opts = {}|
|
33
|
+
alll.find { |x| x.username == username }
|
34
|
+
end
|
35
|
+
|
36
|
+
finder :email do |email, opts = {}|
|
37
|
+
alll.find { |x| x.email == email }
|
38
|
+
end
|
39
|
+
|
40
|
+
finder :dn do |dn, opts = {}|
|
41
|
+
alll.find { |x| x.ldap_id == dn }
|
42
|
+
end
|
43
|
+
|
44
|
+
import :ldap do |user|
|
45
|
+
create(user.email, SecureRandom.hex(8), {
|
46
|
+
name: user.full_name,
|
47
|
+
username: user.username,
|
48
|
+
extern_uid: user.dn,
|
49
|
+
provider: 'ldap',
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
def create(email, password, opts = {})
|
54
|
+
User.build(endpoint, connection.create_user(email, password, opts))
|
55
|
+
end
|
32
56
|
|
33
|
-
|
34
|
-
|
35
|
-
page += 1
|
36
|
-
end
|
57
|
+
def group_members(id, &block)
|
58
|
+
return to_enum(:group_members, id) unless block_given?
|
37
59
|
|
38
|
-
|
39
|
-
User.build(endpoint.endpoint_name, object)
|
40
|
-
end
|
60
|
+
paginate ->(page){ connection.group_members(id, page: page) }, ->(object){ block.call User.build(endpoint, object) }
|
41
61
|
end
|
42
62
|
|
43
63
|
private
|
@@ -13,16 +13,12 @@ module Mooset
|
|
13
13
|
})
|
14
14
|
}
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
}
|
19
|
-
|
20
|
-
def users
|
21
|
-
@users ||= UserSearch.new(self)
|
16
|
+
resource :users do
|
17
|
+
UserSearch.new(self)
|
22
18
|
end
|
23
19
|
|
24
|
-
|
25
|
-
|
20
|
+
resource :groups do
|
21
|
+
GroupSearch.new(self)
|
26
22
|
end
|
27
23
|
|
28
24
|
def write(user)
|
@@ -2,24 +2,22 @@ module Mooset
|
|
2
2
|
module Endpoints
|
3
3
|
class Ldap
|
4
4
|
class Group < Models::Group
|
5
|
+
attribute :dn, String
|
5
6
|
attribute :provider, String, default: "ldap"
|
7
|
+
finders [:dn, :name]
|
6
8
|
|
7
|
-
def self.build(
|
9
|
+
def self.build(endpoint, params)
|
8
10
|
group = Optional.new(params)
|
9
11
|
new(
|
10
|
-
|
11
|
-
id: group[:dn].value,
|
12
|
-
|
13
|
-
|
14
|
-
users_from(endpoint_name, Many.new(users)).values
|
15
|
-
end.value,
|
12
|
+
endpoint: endpoint,
|
13
|
+
id: group[:dn].first.value,
|
14
|
+
dn: group[:dn].first.value,
|
15
|
+
name: group[:cn].first.value
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
users.
|
21
|
-
Ldap::User.build(endpoint_name, id: user)
|
22
|
-
end
|
19
|
+
def members
|
20
|
+
endpoint.users.find(memberof: id)
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Mooset
|
2
|
+
module Endpoints
|
3
|
+
class Ldap
|
4
|
+
class LdapSearch
|
5
|
+
include Findable
|
6
|
+
GROUP_FILTER = "(objectClass=group)"
|
7
|
+
|
8
|
+
attr_reader :endpoint
|
9
|
+
|
10
|
+
def initialize(endpoint, default_search)
|
11
|
+
@endpoint = endpoint
|
12
|
+
@default_search = default_search
|
13
|
+
end
|
14
|
+
|
15
|
+
finder :dn do |dn, base: nil|
|
16
|
+
s = base.nil? ? @default_search : dn
|
17
|
+
b = base.nil? ? dn : base
|
18
|
+
|
19
|
+
query(s, base: b)
|
20
|
+
end
|
21
|
+
|
22
|
+
finder :name do |name, opts = {}|
|
23
|
+
query("(&(objectclass=group)(cn=#{name}))")
|
24
|
+
end
|
25
|
+
|
26
|
+
finder :memberof do |dn, base: endpoint.treebase|
|
27
|
+
query("(&(objectclass=person)(memberof=#{dn})(!(useraccountcontrol:1.2.840.113556.1.4.803:=2)))", base: base)
|
28
|
+
end
|
29
|
+
|
30
|
+
def query(filter = @default_search, base: endpoint.treebase)
|
31
|
+
return to_enum(:query, filter, base: base) unless block_given?
|
32
|
+
|
33
|
+
connection.search(base: base, filter: filter) do |object|
|
34
|
+
if object[:objectclass] && object[:objectclass].include?("group")
|
35
|
+
r = Group.build(endpoint, object)
|
36
|
+
elsif object[:objectclass] && object[:objectclass].include?("user")
|
37
|
+
r = User.build(endpoint, object)
|
38
|
+
elsif object[:objectclass] && object[:objectclass].include?("organizationalUnit")
|
39
|
+
r = Ou.build(endpoint, object)
|
40
|
+
else
|
41
|
+
raise "Unknown objectclass #{object[:objectclass]}"
|
42
|
+
end
|
43
|
+
|
44
|
+
yield r
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def connection
|
51
|
+
@endpoint.connection
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -41,26 +41,21 @@ module Mooset
|
|
41
41
|
end
|
42
42
|
|
43
43
|
class User < Models::User
|
44
|
-
|
44
|
+
finders [:dn, :username, :email]
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
Ldap::Group.build(endpoint_name, id: group)
|
49
|
-
end
|
50
|
-
end
|
46
|
+
attribute :provider, String, default: "ldap"
|
47
|
+
attribute :dn, String
|
51
48
|
|
52
|
-
def self.build(
|
49
|
+
def self.build(endpoint, params)
|
53
50
|
user = Optional.new(params)
|
54
51
|
|
55
52
|
self.new(
|
56
|
-
|
57
|
-
id: user[:dn].value,
|
58
|
-
dn: user[:dn].value,
|
53
|
+
endpoint: endpoint,
|
54
|
+
id: user[:dn].first.value,
|
55
|
+
dn: user[:dn].first.value,
|
59
56
|
email: user[:mail].first.value,
|
60
57
|
full_name: user[:cn].first.value,
|
61
|
-
username: user[:sAMAccountName].value,
|
62
|
-
memberof: user[:memberof].within { |groups| groups_from(endpoint_name, Many.new(groups)).values }.value,
|
63
|
-
useraccountcontrol: AccountControl.decode(user[:useraccountcontrol][0].to_i),
|
58
|
+
username: user[:sAMAccountName].first.value,
|
64
59
|
)
|
65
60
|
end
|
66
61
|
end
|
@@ -11,38 +11,26 @@ module Mooset
|
|
11
11
|
attribute :bind_dn, String
|
12
12
|
attribute :bind_password, String
|
13
13
|
attribute :treebase, String
|
14
|
+
attribute :encryption, Symbol
|
14
15
|
attribute :connection, Object, default: Proc.new { |ldap, attribute|
|
15
16
|
connection = Net::LDAP.new
|
16
17
|
connection.host = ldap.host
|
17
18
|
connection.port = ldap.port
|
19
|
+
connection.encryption(ldap.encryption)
|
18
20
|
connection.auth ldap.bind_dn, ldap.bind_password
|
19
21
|
connection
|
20
22
|
}
|
21
23
|
|
22
|
-
attribute :storage, Object, default: Proc.new { Storage::Memory.new(name) }
|
23
|
-
|
24
24
|
def write(*user)
|
25
25
|
raise "Read only endpoint"
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def find(dn)
|
33
|
-
Many.new(query("(objectClass=*)", base: dn)).within do |data|
|
34
|
-
if data[:objectclass] && data[:objectclass].include?("group")
|
35
|
-
Group.build(connection, data)
|
36
|
-
elsif data[:objectclass] && data[:objectclass].include?("user")
|
37
|
-
User.build(connection, data)
|
38
|
-
else
|
39
|
-
raise "Unknown objectclass"
|
40
|
-
end
|
41
|
-
end.values.first
|
28
|
+
resource :users do
|
29
|
+
LdapSearch.new(self, "(objectClass=person)")
|
42
30
|
end
|
43
31
|
|
44
|
-
|
45
|
-
|
32
|
+
resource :groups do
|
33
|
+
LdapSearch.new(self, "(|(objectClass=group)(objectClass=organizationalUnit))")
|
46
34
|
end
|
47
35
|
end
|
48
36
|
end
|
@@ -1,12 +1,54 @@
|
|
1
1
|
module Mooset
|
2
2
|
module Endpoints
|
3
3
|
class Null < Endpoint
|
4
|
-
|
5
|
-
|
4
|
+
class U
|
5
|
+
#include Findable
|
6
|
+
|
7
|
+
def create(u)
|
8
|
+
Models::User.new(id: u.id, username: u.username, email: u.email)
|
9
|
+
end
|
10
|
+
|
11
|
+
def import(from, *args)
|
12
|
+
@logger.info(from, *args)
|
13
|
+
end
|
14
|
+
|
15
|
+
#import :ldap do |u|
|
16
|
+
#create(u)
|
17
|
+
#end
|
18
|
+
end
|
19
|
+
|
20
|
+
class G
|
21
|
+
include Findable
|
22
|
+
|
23
|
+
def create(u)
|
24
|
+
model = Models::Group.new(id: u.id, name: u.name)
|
25
|
+
model.send :define_singleton_method, :'<<' do |other|
|
26
|
+
@logger.info "#{self.id} << #{other.id}"
|
27
|
+
end
|
28
|
+
|
29
|
+
model
|
30
|
+
end
|
31
|
+
|
32
|
+
import :gitlab do |o|
|
33
|
+
logger.info o
|
34
|
+
end
|
35
|
+
|
36
|
+
import :ldap do |gr|
|
37
|
+
g = create(gr)
|
38
|
+
g.send :define_singleton_method, :members do
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
g
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
resource :users do
|
47
|
+
U.new
|
6
48
|
end
|
7
49
|
|
8
|
-
|
9
|
-
|
50
|
+
resource :groups do
|
51
|
+
G.new
|
10
52
|
end
|
11
53
|
end
|
12
54
|
end
|
data/lib/mooset/endpoints.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
require 'mooset/endpoints/endpoint'
|
2
|
+
require 'mooset/endpoints/findable'
|
2
3
|
require 'mooset/endpoints/gitlab'
|
3
4
|
require 'mooset/endpoints/gitlab/user'
|
4
5
|
require 'mooset/endpoints/gitlab/group'
|
6
|
+
require 'mooset/endpoints/gitlab/paginate'
|
5
7
|
require 'mooset/endpoints/gitlab/user_search'
|
6
8
|
require 'mooset/endpoints/gitlab/group_search'
|
7
9
|
require 'mooset/endpoints/ldap'
|
8
10
|
require 'mooset/endpoints/ldap/user'
|
9
11
|
require 'mooset/endpoints/ldap/group'
|
10
|
-
require 'mooset/endpoints/ldap/
|
11
|
-
require 'mooset/endpoints/ldap/
|
12
|
-
require 'mooset/endpoints/console_logger'
|
12
|
+
require 'mooset/endpoints/ldap/ou'
|
13
|
+
require 'mooset/endpoints/ldap/ldap_search'
|
13
14
|
require 'mooset/endpoints/null'
|
14
15
|
|
15
16
|
module Mooset
|
data/lib/mooset/resource.rb
CHANGED
@@ -2,15 +2,29 @@ module Mooset
|
|
2
2
|
class Resource
|
3
3
|
include Virtus.model
|
4
4
|
|
5
|
-
|
6
|
-
attribute :endpoint_name
|
5
|
+
attr_reader :endpoint
|
7
6
|
|
8
|
-
def
|
9
|
-
|
7
|
+
def self.finders(finder_list)
|
8
|
+
define_method :finders do
|
9
|
+
finder_list
|
10
|
+
end
|
10
11
|
end
|
11
12
|
|
12
13
|
def initialize(*args)
|
14
|
+
@endpoint = args[0][:endpoint]
|
15
|
+
|
13
16
|
super(*args)
|
17
|
+
|
18
|
+
@logger = ::Logger.new(STDOUT)
|
19
|
+
@logger.info "{endpoint_name} -- build #{self.class.name} #{args.join(" ")}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json(*args)
|
23
|
+
attributes.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
def finders
|
27
|
+
[]
|
14
28
|
end
|
15
29
|
end
|
16
30
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Mooset
|
2
|
+
class SynchronizeGroups
|
3
|
+
attr_accessor :from, :to, :opts
|
4
|
+
|
5
|
+
def initialize(from, to, opts)
|
6
|
+
@from = from
|
7
|
+
@to = to
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
@from.groups.find(@opts[:query]).each do |group|
|
13
|
+
to_group = @to.groups.find(group)
|
14
|
+
|
15
|
+
if !to_group
|
16
|
+
to_group = @to.groups.import(group)
|
17
|
+
end
|
18
|
+
|
19
|
+
to_member_ids = to_group.members.map(&:id)
|
20
|
+
|
21
|
+
group.members.each do |user|
|
22
|
+
#next unless user.id =~ /Alexandru/
|
23
|
+
|
24
|
+
to_user = @to.users.find(user)
|
25
|
+
|
26
|
+
if !to_user
|
27
|
+
to_user = @to.users.import(user)
|
28
|
+
end
|
29
|
+
|
30
|
+
to_group << to_user unless to_member_ids.include?(to_user.id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/mooset/version.rb
CHANGED
data/lib/mooset.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mooset
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandru Keszeg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gitlab
|
@@ -141,29 +141,28 @@ files:
|
|
141
141
|
- lib/mooset/application.rb
|
142
142
|
- lib/mooset/configuration.rb
|
143
143
|
- lib/mooset/endpoints.rb
|
144
|
-
- lib/mooset/endpoints/console_logger.rb
|
145
144
|
- lib/mooset/endpoints/endpoint.rb
|
145
|
+
- lib/mooset/endpoints/findable.rb
|
146
146
|
- lib/mooset/endpoints/gitlab.rb
|
147
147
|
- lib/mooset/endpoints/gitlab/group.rb
|
148
148
|
- lib/mooset/endpoints/gitlab/group_search.rb
|
149
|
+
- lib/mooset/endpoints/gitlab/paginate.rb
|
149
150
|
- lib/mooset/endpoints/gitlab/user.rb
|
150
151
|
- lib/mooset/endpoints/gitlab/user_search.rb
|
151
152
|
- lib/mooset/endpoints/ldap.rb
|
152
153
|
- lib/mooset/endpoints/ldap/group.rb
|
153
|
-
- lib/mooset/endpoints/ldap/
|
154
|
+
- lib/mooset/endpoints/ldap/ldap_search.rb
|
155
|
+
- lib/mooset/endpoints/ldap/ou.rb
|
154
156
|
- lib/mooset/endpoints/ldap/user.rb
|
155
|
-
- lib/mooset/endpoints/ldap/user_search.rb
|
156
157
|
- lib/mooset/endpoints/null.rb
|
157
158
|
- lib/mooset/models/group.rb
|
158
159
|
- lib/mooset/models/user.rb
|
159
160
|
- lib/mooset/monads.rb
|
160
161
|
- lib/mooset/resource.rb
|
161
|
-
- lib/mooset/storage.rb
|
162
162
|
- lib/mooset/storage/memory.rb
|
163
|
-
- lib/mooset/
|
163
|
+
- lib/mooset/synchronize_group.rb
|
164
164
|
- lib/mooset/version.rb
|
165
165
|
- mooset.gemspec
|
166
|
-
- spec/mooset/endpoints/gitlab_spec.rb
|
167
166
|
- spec/mooset/endpoints/ldap_spec.rb
|
168
167
|
- spec/spec_helper.rb
|
169
168
|
homepage: ''
|
@@ -191,6 +190,5 @@ signing_key:
|
|
191
190
|
specification_version: 4
|
192
191
|
summary: A Ruby library and client for user migration.
|
193
192
|
test_files:
|
194
|
-
- spec/mooset/endpoints/gitlab_spec.rb
|
195
193
|
- spec/mooset/endpoints/ldap_spec.rb
|
196
194
|
- spec/spec_helper.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Mooset
|
2
|
-
module Endpoints
|
3
|
-
class Ldap
|
4
|
-
class GroupSearch
|
5
|
-
GROUP_FILTER = "(objectClass=group)"
|
6
|
-
|
7
|
-
attr_reader :endpoint
|
8
|
-
|
9
|
-
def initialize(endpoint)
|
10
|
-
@endpoint = endpoint
|
11
|
-
end
|
12
|
-
|
13
|
-
def query(filter = GROUP_FILTER, base: endpoint.treebase)
|
14
|
-
connection.search(base: base, filter: filter).collect do |object|
|
15
|
-
Group.build(endpoint.endpoint_name, object)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def all
|
20
|
-
query(GROUP_FILTER)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def connection
|
26
|
-
@endpoint.connection
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Mooset
|
2
|
-
module Endpoints
|
3
|
-
class Ldap
|
4
|
-
class UserSearch
|
5
|
-
USER_FILTER = "(objectClass=person)"
|
6
|
-
|
7
|
-
attr_reader :endpoint
|
8
|
-
|
9
|
-
def initialize(endpoint)
|
10
|
-
@endpoint = endpoint
|
11
|
-
end
|
12
|
-
|
13
|
-
def query(filter = USER_FILTER, base: endpoint.treebase)
|
14
|
-
connection.search(base: base, filter: filter).collect do |object|
|
15
|
-
User.build(endpoint.endpoint_name, object)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def all
|
20
|
-
query(USER_FILTER)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def connection
|
26
|
-
@endpoint.connection
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/mooset/storage.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mooset::Endpoints::Gitlab do
|
4
|
-
let(:storage) { double(exists?: false) }
|
5
|
-
let(:connection) { double }
|
6
|
-
let(:command) { Mooset::Endpoints::Gitlab.new(:gitlab, connection: connection, storage: storage) }
|
7
|
-
|
8
|
-
describe '#write' do
|
9
|
-
let(:user) do
|
10
|
-
double({
|
11
|
-
email: 'email',
|
12
|
-
extern_uid: '1',
|
13
|
-
username: 'username',
|
14
|
-
provider: 'ldap',
|
15
|
-
})
|
16
|
-
end
|
17
|
-
|
18
|
-
it "calls the create user api" do
|
19
|
-
expect(connection).to receive(:create_user).with(user.email, anything,{
|
20
|
-
extern_uid: user.extern_uid,
|
21
|
-
username: user.username,
|
22
|
-
provider: 'ldap',
|
23
|
-
})
|
24
|
-
|
25
|
-
command.write(user)
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'when the user is already imported' do
|
29
|
-
let(:storage) { double }
|
30
|
-
|
31
|
-
it "doesn't create duplicate users" do
|
32
|
-
expect(storage).to receive(:exists?).with(user).and_return(true)
|
33
|
-
expect(connection).not_to receive(:create_user)
|
34
|
-
|
35
|
-
command.write(user)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|