soar-registry-directory 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4505d2bbb4a6b9d47b370ddeaf82d8a9b76231b
4
- data.tar.gz: e4de04def83d9751931f30eb49e9fcaad7acd61c
3
+ metadata.gz: 70a565fb09b0f4af26cfb869c32c41aa5809b27e
4
+ data.tar.gz: 2fb0d1201fce3c266bf570315b2524005a61776b
5
5
  SHA512:
6
- metadata.gz: 44514a249b7af19f67f784abe25868d644bfd91a70e777078a0aa613954c196bab77e915b5270be35b2146e29a9ea22fcc31860854c7eb704ef0a7688864e153
7
- data.tar.gz: 715d8a78da3f01196c2a67d61fe78bcb059fe86458cd3f6d270f318cfb2de46ba66d57731d8753972d3d1bb7b06ed6bdf32cda651a9e053d87b1102d1607330e
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 TEST_PROVIDER=DynamoDb cucumber
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
+
@@ -3,6 +3,7 @@ module Soar
3
3
  module Directory
4
4
  module Error
5
5
  class NoEntriesFound < StandardError; end;
6
+ class MultipleEntriesFound < StandardError; end;
6
7
  end
7
8
  end
8
9
  end
@@ -1,6 +1,7 @@
1
1
  require 'soar/registry/directory/error'
2
2
  require 'soar/registry/directory/provider/stub'
3
3
  require 'soar/registry/directory/provider/dynamo_db'
4
+ require 'soar/registry/directory/provider/ldap'
4
5
 
5
6
  module Soar
6
7
  module Registry
@@ -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: nil, table: nil, primary_key: nil, index: nil, configuration: nil)
20
+ def initialize(credentials: , table: , index: , configuration: )
22
21
  @table_name = table
23
- @primary_key = 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}_index"}) if @index.include?(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: nil, primary_key: nil, index: nil)
19
+ def initialize(table: , index: )
20
20
  @table = table
21
- @primary_key = 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": {
@@ -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": "email_index",
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,
@@ -1,5 +1,6 @@
1
1
  require 'soar/registry/directory/test/provider/stub'
2
2
  require 'soar/registry/directory/test/provider/dynamo_db'
3
+ require 'soar/registry/directory/test/provider/ldap'
3
4
 
4
5
  module Soar
5
6
  module Registry
@@ -19,7 +19,6 @@ module Soar
19
19
  credentials: @configuration['provider']['credentials'],
20
20
  table: @table,
21
21
  index: @index,
22
- primary_key: @index[0],
23
22
  configuration: @configuration['provider']['config']
24
23
  })
25
24
  @directory = Soar::Registry::Directory.new(provider)
@@ -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 = ["identity_id", "email", "entity_id"]
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: 1.0.0
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.28
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.28
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: