soar-registry-directory 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -4
- data/lib/soar/registry/directory/error.rb +1 -0
- data/lib/soar/registry/directory/model.rb +1 -0
- data/lib/soar/registry/directory/provider/dynamo_db.rb +3 -4
- data/lib/soar/registry/directory/provider/ldap.rb +103 -0
- data/lib/soar/registry/directory/provider/stub.rb +2 -2
- data/lib/soar/registry/directory/test/fixtures/entries.json +0 -4
- data/lib/soar/registry/directory/test/fixtures/entries.ldif +0 -0
- data/lib/soar/registry/directory/test/fixtures/table_structure.json +1 -22
- data/lib/soar/registry/directory/test/orchestrator.rb +1 -0
- data/lib/soar/registry/directory/test/provider/dynamo_db.rb +0 -1
- data/lib/soar/registry/directory/test/provider/ldap.rb +132 -0
- data/lib/soar/registry/directory/test/provider/stub.rb +1 -2
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70a565fb09b0f4af26cfb869c32c41aa5809b27e
|
4
|
+
data.tar.gz: 2fb0d1201fce3c266bf570315b2524005a61776b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfbebba8afea49661752f2fe56a23f57c3874c3595af6b23f90fee6a30697258733b83836254df42e9552f1d841de4c8025ee7b7359f7be5871bd428cb72a049
|
7
|
+
data.tar.gz: 12784a7f75d25c92dabdcd1f3fa88ec779bac1dfd5173507f0a29767ffc8ac60ef3e5816e52ac9ddb05b57f92bb92a32e69320dee5a1c0616f4b191c97b66181
|
data/README.md
CHANGED
@@ -23,7 +23,6 @@ Create an instance of the stub provider by passing in the name, primary key and
|
|
23
23
|
> require 'soar/registry/directory'
|
24
24
|
> provider = Soar::Registry::Directory::Provider::Stub.new({
|
25
25
|
table: "mytable",
|
26
|
-
primary_key: "uuid",
|
27
26
|
index: ["uuid", "email"]
|
28
27
|
})
|
29
28
|
```
|
@@ -36,7 +35,6 @@ Create an instance of the stub provider by passing in the name, primary key and
|
|
36
35
|
},
|
37
36
|
table: "mytable",
|
38
37
|
index: ['uuid', 'email'],
|
39
|
-
primary_key: "uuid",
|
40
38
|
configuration: {
|
41
39
|
region: 'us-west-2'
|
42
40
|
endpoint: 'http://localhost:8000'
|
@@ -45,6 +43,23 @@ Create an instance of the stub provider by passing in the name, primary key and
|
|
45
43
|
|
46
44
|
```
|
47
45
|
|
46
|
+
### LDAP Provider
|
47
|
+
```ruby
|
48
|
+
> provider = Soar::Registry::Directory::Provider::Ldap.new({
|
49
|
+
base: 'dc=hetzner,dc=co,dc=za',
|
50
|
+
index: ['entryuuid', 'mail'],
|
51
|
+
config: {
|
52
|
+
host: 'localhost',
|
53
|
+
port: 389
|
54
|
+
},
|
55
|
+
attributes: ['entryuuid', 'cn', 'mail', 'sn'],
|
56
|
+
credentials: {
|
57
|
+
username: 'cn=admin,dc=hetzner,dc=co,dc=za'
|
58
|
+
password: 'secret'
|
59
|
+
}
|
60
|
+
})
|
61
|
+
```
|
62
|
+
|
48
63
|
### The Model
|
49
64
|
```ruby
|
50
65
|
> directory = Soar::Registry::Directory.new(provider)
|
@@ -70,8 +85,8 @@ exit $EXIT_CODE
|
|
70
85
|
|
71
86
|
#### Local
|
72
87
|
```bash
|
73
|
-
$ docker-compose --file docker-compose.dynamo_db.yml up
|
74
|
-
$ CONFIG_FILE=config.dynamo_db.yml
|
88
|
+
$ docker-compose --file docker-compose.dynamo_db.yml up --remove-orphans
|
89
|
+
$ CONFIG_FILE=config.dynamo_db.yml TEST_ORCHESTRATION_PROVIDER=DynamoDb cucumber
|
75
90
|
```
|
76
91
|
|
77
92
|
#### CI
|
@@ -80,3 +95,19 @@ docker-compose --file docker-compose.ci.dynamo_db.yml up --abort-on-container-ex
|
|
80
95
|
EXIT_CODE=$(docker ps -a -f "name=soar-registry-directory-test-provider-dynamo_db" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
81
96
|
exit $EXIT_CODE
|
82
97
|
```
|
98
|
+
|
99
|
+
### LDAP provider
|
100
|
+
|
101
|
+
#### Local
|
102
|
+
```bash
|
103
|
+
$ docker-compose --file docker-compose.ldap.yml up --remove-orphans
|
104
|
+
$ CONFIG_FILE=config.ldap.yml TEST_ORCHESTRATION_PROVIDER=Ldap cucumber
|
105
|
+
```
|
106
|
+
|
107
|
+
#### CI
|
108
|
+
```bash
|
109
|
+
docker-compose --file docker-compose.ci.ldap.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
|
110
|
+
EXIT_CODE=$(docker ps -a -f "name=soar-registry-directory-test-provider-ldap" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
111
|
+
exit $EXIT_CODE
|
112
|
+
```
|
113
|
+
|
@@ -14,13 +14,12 @@ module Soar
|
|
14
14
|
##
|
15
15
|
# @param credentials [Hash] { username: 'username', password: 'secret'}
|
16
16
|
# @param table [String]
|
17
|
-
# @param primary_key [String]
|
18
17
|
# @param index [Array] primary key should be the first item
|
19
18
|
# @param configuration [Hash] { region: 'us-west-2', endpoint: 'http://localhost:8000' }
|
20
19
|
##
|
21
|
-
def initialize(credentials:
|
20
|
+
def initialize(credentials: , table: , index: , configuration: )
|
22
21
|
@table_name = table
|
23
|
-
@primary_key =
|
22
|
+
@primary_key = index[0]
|
24
23
|
@index = index
|
25
24
|
@credentials = Hashie.symbolize_keys(credentials)
|
26
25
|
configuration[:credentials] = Aws::Credentials.new(@credentials[:username], @credentials[:password])
|
@@ -70,7 +69,7 @@ module Soar
|
|
70
69
|
}
|
71
70
|
}
|
72
71
|
|
73
|
-
options.merge!({index_name: "#{key}
|
72
|
+
options.merge!({index_name: "#{key}-index"}) if @index.include?(key)
|
74
73
|
identity = @client.query(options)
|
75
74
|
identity.items.map { |item|
|
76
75
|
Hashie.stringify_keys(item)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'soar/registry/directory/error'
|
2
|
+
require 'net/ldap'
|
3
|
+
|
4
|
+
module Soar
|
5
|
+
module Registry
|
6
|
+
module Directory
|
7
|
+
module Provider
|
8
|
+
class Ldap
|
9
|
+
|
10
|
+
##
|
11
|
+
# @param config [Hash]
|
12
|
+
# @param base [String] ldap tree base eg 'dc=hetzner,dc=co,dc=za'
|
13
|
+
# @param attributes [Array] array of attributes to return for queries
|
14
|
+
# @param credentials [Hash]
|
15
|
+
##
|
16
|
+
def initialize(config: , base: , attributes: , index: , credentials: )
|
17
|
+
@base = base
|
18
|
+
@index = index
|
19
|
+
@attributes = attributes
|
20
|
+
@config = {
|
21
|
+
host: config[:host],
|
22
|
+
port: config[:port],
|
23
|
+
auth: {
|
24
|
+
method: :simple,
|
25
|
+
username: credentials[:username],
|
26
|
+
password: credentials[:password]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
@ldap = Net::LDAP.new(@config)
|
30
|
+
@ldap.bind
|
31
|
+
end
|
32
|
+
|
33
|
+
def put(entry)
|
34
|
+
@ldap.add({
|
35
|
+
dn: entry[:dn],
|
36
|
+
attributes: entry[:attributes]
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @param [String] uuid primary key of the identity
|
42
|
+
# @return [Hash] the identity
|
43
|
+
# @raise [Soar::Registry::Directory::Error::NoEntriesFound] if primary key not found
|
44
|
+
# @raise [Soar::Registry::Directory::Error::MultipleEntriesFound] if multiple matches found
|
45
|
+
##
|
46
|
+
def fetch(uuid)
|
47
|
+
result = @ldap.search({
|
48
|
+
base: @base,
|
49
|
+
attributes: @attributes,
|
50
|
+
filter: Net::LDAP::Filter.eq(@index[0], uuid),
|
51
|
+
return_result: true
|
52
|
+
})
|
53
|
+
raise Soar::Registry::Directory::Error::NoEntriesFound if result.empty?
|
54
|
+
raise Soar::Registry::Directory::Error::MultipleEntriesFound if result.length > 1
|
55
|
+
response = {}
|
56
|
+
@attributes.each { |attribute|
|
57
|
+
response[attribute.to_sym] = result[0][attribute.to_sym][0]
|
58
|
+
}
|
59
|
+
response
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
##
|
64
|
+
# @param key, named index [String]
|
65
|
+
# @param value [String]
|
66
|
+
# @return [Array] list of identities
|
67
|
+
# @raise [ArgumentError] if value or named index is not specified
|
68
|
+
##
|
69
|
+
def search(key, value)
|
70
|
+
result = []
|
71
|
+
entries = @ldap.search({
|
72
|
+
base: @base,
|
73
|
+
filter: Net::LDAP::Filter.eq(key, value),
|
74
|
+
attributes: @attributes,
|
75
|
+
return_result: true
|
76
|
+
})
|
77
|
+
|
78
|
+
entries.each { |entry|
|
79
|
+
response = {}
|
80
|
+
@attributes.each { |attribute|
|
81
|
+
response[attribute.to_sym] = entry[attribute.to_sym][0]
|
82
|
+
}
|
83
|
+
result << response
|
84
|
+
}
|
85
|
+
return result
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# @return [Array] a list of primary keys and global secondary indexes
|
90
|
+
##
|
91
|
+
def index
|
92
|
+
@index
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete(dn)
|
96
|
+
@ldap.delete(dn: dn)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -16,9 +16,9 @@ module Soar
|
|
16
16
|
# @param primary_key [String]
|
17
17
|
# @param index [Array] primary key should be the first item
|
18
18
|
##
|
19
|
-
def initialize(table:
|
19
|
+
def initialize(table: , index: )
|
20
20
|
@table = table
|
21
|
-
@primary_key =
|
21
|
+
@primary_key = index[0]
|
22
22
|
@index = index
|
23
23
|
@@interface.clear
|
24
24
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
[
|
2
2
|
{
|
3
3
|
"uuid": "identity-62936e70-1815-439b-bf89-8492855a7e6b",
|
4
|
-
"entity_id": "entity-2d931510-d99f-494a-8c67-87feb05e1594",
|
5
4
|
"email": "test+publisher@hetzner.co.za",
|
6
5
|
"roles": {
|
7
6
|
"staff": {
|
@@ -14,7 +13,6 @@
|
|
14
13
|
},
|
15
14
|
{
|
16
15
|
"uuid": "identity-43353f18-8afe-11e6-ae22-56b6b6499611",
|
17
|
-
"entity_id": "entity-2d931510-d99f-494a-8c67-87feb05e1594",
|
18
16
|
"email": "test+consumer@hetzner.co.za",
|
19
17
|
"roles": {
|
20
18
|
"staff": {},
|
@@ -26,7 +24,6 @@
|
|
26
24
|
},
|
27
25
|
{
|
28
26
|
"uuid": "identity-820d5660-2204-4f7d-8c04-746313439b81",
|
29
|
-
"entity_id": "entity-bad85eb9-0713-4da7-8d36-07a8e4b00eab",
|
30
27
|
"email": "admin@hetzner.co.za",
|
31
28
|
"roles": {
|
32
29
|
"staff": {},
|
@@ -48,7 +45,6 @@
|
|
48
45
|
},
|
49
46
|
{
|
50
47
|
"uuid": "identity-1ff472a6-8df3-4f13-82c3-89fde26db3cf",
|
51
|
-
"entity_id": "entity-bad85eb9-0713-4da7-8d36-07a8e4b00eab",
|
52
48
|
"email": "none@example.com",
|
53
49
|
"client_nr": "C123456789",
|
54
50
|
"roles": {
|
File without changes
|
@@ -11,10 +11,6 @@
|
|
11
11
|
"attribute_name": "uuid",
|
12
12
|
"attribute_type": "S"
|
13
13
|
},
|
14
|
-
{
|
15
|
-
"attribute_name": "entity_id",
|
16
|
-
"attribute_type": "S"
|
17
|
-
},
|
18
14
|
{
|
19
15
|
"attribute_name": "email",
|
20
16
|
"attribute_type": "S"
|
@@ -22,7 +18,7 @@
|
|
22
18
|
],
|
23
19
|
"global_secondary_indexes": [
|
24
20
|
{
|
25
|
-
"index_name": "
|
21
|
+
"index_name": "email-index",
|
26
22
|
"key_schema": [
|
27
23
|
{
|
28
24
|
"attribute_name": "email",
|
@@ -32,23 +28,6 @@
|
|
32
28
|
"projection": {
|
33
29
|
"projection_type": "ALL"
|
34
30
|
|
35
|
-
},
|
36
|
-
"provisioned_throughput": {
|
37
|
-
"read_capacity_units": 10,
|
38
|
-
"write_capacity_units": 10
|
39
|
-
}
|
40
|
-
},
|
41
|
-
{
|
42
|
-
"index_name": "entity_id_index",
|
43
|
-
"key_schema": [
|
44
|
-
{
|
45
|
-
"attribute_name": "entity_id",
|
46
|
-
"key_type": "HASH"
|
47
|
-
}
|
48
|
-
],
|
49
|
-
"projection": {
|
50
|
-
"projection_type": "ALL"
|
51
|
-
|
52
31
|
},
|
53
32
|
"provisioned_throughput": {
|
54
33
|
"read_capacity_units": 10,
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'soar/registry/directory'
|
2
|
+
|
3
|
+
module Soar
|
4
|
+
module Registry
|
5
|
+
module Directory
|
6
|
+
module Test
|
7
|
+
module Provider
|
8
|
+
class Ldap
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@configuration = YAML.load_file("config/#{ENV['CONFIG_FILE']}")
|
12
|
+
@base = @configuration['provider']['base']
|
13
|
+
@config = {
|
14
|
+
host: @configuration['provider']['config']['host'],
|
15
|
+
port: @configuration['provider']['config']['port']
|
16
|
+
}
|
17
|
+
@credentials = {
|
18
|
+
username: @configuration['provider']['credentials']['username'],
|
19
|
+
password: @configuration['provider']['credentials']['password']
|
20
|
+
}
|
21
|
+
@index = @configuration['provider']['index']
|
22
|
+
@entries = [{
|
23
|
+
dn: "cn=John Smith,#{@base}",
|
24
|
+
attributes: {
|
25
|
+
cn: "John Smith",
|
26
|
+
mail: "test@example.com",
|
27
|
+
objectclass: ["inetOrgPerson", "top"],
|
28
|
+
sn: "Smith"
|
29
|
+
}
|
30
|
+
}, {
|
31
|
+
dn: "cn=Sarel Cilliers,#{@base}",
|
32
|
+
attributes: {
|
33
|
+
cn: "Sarel Cilliers",
|
34
|
+
mail: "sarel@example.com",
|
35
|
+
objectclass: ["inetOrgPerson", "top"],
|
36
|
+
sn: "Cilliers"
|
37
|
+
}
|
38
|
+
}]
|
39
|
+
end
|
40
|
+
|
41
|
+
def given_configured_directory
|
42
|
+
provider = Soar::Registry::Directory::Provider::Ldap.new({
|
43
|
+
base: @base,
|
44
|
+
index: @index,
|
45
|
+
config: {
|
46
|
+
host: @config[:host],
|
47
|
+
port: @config[:port]
|
48
|
+
},
|
49
|
+
attributes: ['entryuuid', 'cn', 'mail', 'sn'],
|
50
|
+
credentials: {
|
51
|
+
username: @credentials[:username],
|
52
|
+
password: @credentials[:password]
|
53
|
+
}
|
54
|
+
})
|
55
|
+
@directory = Soar::Registry::Directory.new(provider)
|
56
|
+
@entries.each { |entry|
|
57
|
+
provider.delete(entry[:dn])
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Adds @entries to datastore using ldap protocol
|
63
|
+
# Adds entryuuid to @entries
|
64
|
+
##
|
65
|
+
def given_existing_data
|
66
|
+
@entries.each{ |entry|
|
67
|
+
@directory.put(entry)
|
68
|
+
result = @directory.search("mail", entry[:attributes][:mail])
|
69
|
+
entry[:attributes][:entryuuid] = result[0][:entryuuid]
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def put_entry
|
74
|
+
@directory.put(@entries[0])
|
75
|
+
result = @directory.search("mail", @entries[0][:attributes][:mail])
|
76
|
+
@entries[0][:attributes][:entryuuid] = result[0][:entryuuid]
|
77
|
+
end
|
78
|
+
|
79
|
+
def search_for_entry
|
80
|
+
@result = @directory.search("mail", @entries[0][:attributes][:mail])
|
81
|
+
end
|
82
|
+
|
83
|
+
def request_index
|
84
|
+
@result = @directory.index
|
85
|
+
end
|
86
|
+
|
87
|
+
def fetch_entry
|
88
|
+
begin
|
89
|
+
@result = @directory.fetch(@entries[0][:attributes][:entryuuid])
|
90
|
+
rescue Soar::Registry::Directory::Error::NoEntriesFound
|
91
|
+
@error = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def persisted?
|
96
|
+
result = @directory.fetch(@entries[0][:attributes][:entryuuid])
|
97
|
+
entry = @entries[0][:attributes]
|
98
|
+
entry.delete(:objectclass)
|
99
|
+
result == entry
|
100
|
+
end
|
101
|
+
|
102
|
+
def returned?
|
103
|
+
entry = @entries[0][:attributes]
|
104
|
+
entry.delete(:objectclass)
|
105
|
+
@result == [entry]
|
106
|
+
end
|
107
|
+
|
108
|
+
def index?
|
109
|
+
@result == @index
|
110
|
+
end
|
111
|
+
|
112
|
+
def single_entry?
|
113
|
+
entry = @entries[0][:attributes]
|
114
|
+
entry.delete(:objectclass)
|
115
|
+
@result == entry
|
116
|
+
end
|
117
|
+
|
118
|
+
def no_entries_found?
|
119
|
+
@error == true
|
120
|
+
end
|
121
|
+
|
122
|
+
def no_matching_entries?
|
123
|
+
@result == []
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -12,12 +12,11 @@ module Soar
|
|
12
12
|
"identifier" => SecureRandom.hex
|
13
13
|
}
|
14
14
|
|
15
|
-
@@index = ["
|
15
|
+
@@index = ["uuid", "identifier"]
|
16
16
|
|
17
17
|
def given_configured_directory
|
18
18
|
provider = Soar::Registry::Directory::Provider::Stub.new({
|
19
19
|
table: "identities",
|
20
|
-
primary_key: "uuid",
|
21
20
|
index: @@index
|
22
21
|
})
|
23
22
|
@directory = Soar::Registry::Directory.new(provider)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soar-registry-directory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Mulder
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
version: '2.6'
|
68
68
|
- - ">="
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: 2.6.
|
70
|
+
version: 2.6.38
|
71
71
|
type: :runtime
|
72
72
|
prerelease: false
|
73
73
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
version: '2.6'
|
78
78
|
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version: 2.6.
|
80
|
+
version: 2.6.38
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: hashie
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,6 +98,20 @@ dependencies:
|
|
98
98
|
- - ">="
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: 3.4.6
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: net-ldap
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 0.15.0
|
108
|
+
type: :runtime
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - "~>"
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.15.0
|
101
115
|
description: Directories for soar registries
|
102
116
|
email: charles.mulder@hetzner.co.za
|
103
117
|
executables: []
|
@@ -109,11 +123,14 @@ files:
|
|
109
123
|
- lib/soar/registry/directory/error.rb
|
110
124
|
- lib/soar/registry/directory/model.rb
|
111
125
|
- lib/soar/registry/directory/provider/dynamo_db.rb
|
126
|
+
- lib/soar/registry/directory/provider/ldap.rb
|
112
127
|
- lib/soar/registry/directory/provider/stub.rb
|
113
128
|
- lib/soar/registry/directory/test/fixtures/entries.json
|
129
|
+
- lib/soar/registry/directory/test/fixtures/entries.ldif
|
114
130
|
- lib/soar/registry/directory/test/fixtures/table_structure.json
|
115
131
|
- lib/soar/registry/directory/test/orchestrator.rb
|
116
132
|
- lib/soar/registry/directory/test/provider/dynamo_db.rb
|
133
|
+
- lib/soar/registry/directory/test/provider/ldap.rb
|
117
134
|
- lib/soar/registry/directory/test/provider/stub.rb
|
118
135
|
homepage: https://gitlab.host-h.net/registries/directory
|
119
136
|
licenses:
|