aserto 0.20.6 → 0.30.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc8ec9b57f67226df562850ca0188c27b310de08b2ac716d30143c2c603b84fd
4
- data.tar.gz: 845f1cdf67e54411d004b2a91b0a37ba02d709c949512110a8158552c67f48a3
3
+ metadata.gz: ddb26b2da994a8a4f72162f227590060a990a31d16639994b5cd2e4bd9ce538f
4
+ data.tar.gz: e6969585d13f94a6e410d8763647cbc3dca69402969a194db2674239514adeeb
5
5
  SHA512:
6
- metadata.gz: dda8391014951485e822508b064667ff3bfd649b412df436fe019fb3c351fc891bed770093bf9a4c8db6e1bf791a14ed3dd6e23f9bcb6def14e5c26b69f49745
7
- data.tar.gz: 675b6dbcc2c38a8d094a3baa59de6c786a5ddd07ad0f8ab91975b70645f279df28bcfd856c5ec33a68664afe365d4852fcfc7599c91fbdd881b0ff50be3346c5
6
+ metadata.gz: c0202011d8ce67f9fc48e361fdbd00b9239e291aa7bc60e5773eed58252dec41fdbac16e28ea25f0ff54d4652a0eee247ec048f59e6df5b1ae1bc5d254638244
7
+ data.tar.gz: a2c5e23bcb6e18ee1babb1c13d0e39912c32aa70595c5ce8dae69e24e0f10c6c37e7251f6dad0d5059fbe801dc8bf3d5ddde3ba806c071ae96b52afd1ba84f49
data/README.md CHANGED
@@ -23,7 +23,7 @@ gem install aserto
23
23
 
24
24
  ## Directory
25
25
 
26
- The Directory APIs can be used to get or set object instances and relation instances. They can also be used to check whether a user has a permission or relation on an object instance.
26
+ The Directory APIs can be used to get or set object instances and relation instances. They can also be used to check whether a user has permission or relation on an object instance.
27
27
 
28
28
  ### Directory Client
29
29
 
@@ -32,7 +32,7 @@ You can initialize a directory client as follows:
32
32
  ```ruby
33
33
  require 'aserto/directory/client'
34
34
 
35
- directory_client = Aserto::Directory::Client.new(
35
+ directory_client = Aserto::Directory::V3::Client.new(
36
36
  url: "directory.eng.aserto.com:8443",
37
37
  tenant_id: "aserto-tenant-id",
38
38
  api_key: "basic directory api key",
@@ -42,87 +42,9 @@ directory_client = Aserto::Directory::Client.new(
42
42
  - `url`: hostname:port of directory service (_required_)
43
43
  - `api_key`: API key for directory service (_required_ if using hosted directory)
44
44
  - `tenant_id`: Aserto tenant ID (_required_ if using hosted directory)
45
- - `cert_path`: Path to the grpc service certificate when connecting to local topaz instance.
45
+ - `cert_path`: Path to the grpc service certificate when connecting to the local topaz instance.
46
46
 
47
- ### Getting objects and relations
48
- Get an object instance with the type `type-name` and the key `object-key`. For example:
49
-
50
- ```ruby
51
- user = directory_client.object(type: 'user', key: 'euang@acmecorp.com')
52
- ```
53
-
54
- Get an array of relations of a certain type for an object instance. For example:
55
-
56
- ```ruby
57
- identity = 'euang@acmecorp.com';
58
- relations = directory_client.relation(
59
- {
60
- subject: {
61
- type: 'user',
62
- },
63
- object: {
64
- type: 'identity',
65
- key: identity
66
- },
67
- relation: {
68
- name: 'identifier',
69
- objectType: 'identity'
70
- }
71
- }
72
- )
73
- ```
74
-
75
- ### Setting objects and relations
76
-
77
- Create a new object
78
- ```ruby
79
- user = directory_client.set_object(object: { type: "user", key: "test-object", display_name: "test object" })
80
- identity = directory_client.set_object(object: { type: "identity", key: "test-identity" })
81
- ```
82
-
83
- Update an existing object
84
- ```ruby
85
- user = directory_client.set_object(object: { type: "user", key: "test-object", display_name: "test object" })
86
- user.display_name = 'test object edit'
87
- updated_user = directory_client.set_object(object: user)
88
- ```
89
-
90
- Create a new relation
91
- ```ruby
92
- directory_client.set_relation(
93
- subject: { type: "user", "test-object" },
94
- relation: "identifier",
95
- object: { type: "identity", key: "test-identity" }
96
- )
97
- ```
98
-
99
- Delete a relation
100
- ```ruby
101
- pp client.delete_relation(
102
- subject: { type: "user", key: "test-object" },
103
- relation: { name: "identifier", object_type: "identity" },
104
- object: { type: "identity", key: "test-identity" }
105
- )
106
- ```
107
-
108
- ### Checking permissions and relations
109
- Check permission
110
- ```ruby
111
- directory_client.check_permission(
112
- subject: { type: "user", key: "011a88bc-7df9-4d92-ba1f-2ff319e101e1" },
113
- permission: { name: "read" },
114
- object: { type: "group", key: "executive" }
115
- )
116
- ```
117
-
118
- Check relation
119
- ```ruby
120
- directory_client.check_relation(
121
- subject: { type: "user", key: "dfdadc39-7335-404d-af66-c77cf13a15f8" },
122
- relation: { name: "identifier", object_type: "identity" },
123
- object: { type: "identity", key: "euang@acmecorp.com" }
124
- )
125
- ```
47
+ See [Aserto::Directory::V3::Client](https://rubydoc.info/gems/aserto/Aserto/Directory/V3/Client) for full documentation
126
48
 
127
49
  ## Authorizer
128
50
  `Aserto::Authorization` is a middleware that allows Ruby applications to use Aserto as the Authorization provider.
@@ -150,7 +72,7 @@ The middleware accepts the following optional parameters:
150
72
  | cert_path | `""` | Path to the grpc service certificate when connecting to local topaz instance. |
151
73
  | decision | `"allowed"` | The decision that will be used by the middleware when creating an authorizer request. |
152
74
  | logger | `STDOUT` | The logger to be used by the middleware. |
153
- | identity_mapping | `{ type: :none }` | The strategy for retrieving the identity, possible values: `:jwt, :sub, :none` |
75
+ | identity_mapping | `{ type: :none }` | The strategy for retrieving the identity, possible values: `:jwt, :sub, :manual, :none` |
154
76
  | disabled_for | `[{}]` | Which path and actions to skip the authorization for. |
155
77
  | on_unauthorized | `-> { return [403, {}, ["Forbidden"]] }`| A lambda that is executed when the authorization fails. |
156
78
 
@@ -172,6 +94,14 @@ config.identity_mapping = {
172
94
  }
173
95
  ```
174
96
 
97
+ ```ruby
98
+ # configure the middleware to use a manual identity.
99
+ config.identity_mapping = {
100
+ type: :manual,
101
+ value: "my-identity",
102
+ }
103
+ ```
104
+
175
105
  The whole identity resolution can be overwritten by providing a custom function.
176
106
  ```ruby
177
107
  # config/initializers/aserto.rb
@@ -190,7 +120,7 @@ end
190
120
  By default, when computing the policy path, the middleware:
191
121
  * converts all slashes to dots
192
122
  * converts any character that is not alpha, digit, dot or underscore to underscore
193
- * converts uppercase characters in the URL path to lowercases
123
+ * converts uppercase characters in the URL path to lowercase
194
124
 
195
125
  This behaviour can be overwritten by providing a custom function:
196
126
 
@@ -206,7 +136,7 @@ end
206
136
  ```
207
137
 
208
138
  ### Resource
209
- A resource can be any structured data that the authorization policy uses to evaluate decisions. By default, middleware does not include a resource in authorization calls.
139
+ A resource can be any structured data the authorization policy uses to evaluate decisions. By default, middleware does not include a resource in authorization calls.
210
140
 
211
141
  This behaviour can be overwritten by providing a custom function:
212
142
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.20.6
1
+ 0.30.1
@@ -13,6 +13,7 @@ module Aserto
13
13
  INTERNAL_MAPPING = {
14
14
  unknown: Aserto::Authorizer::V2::Api::IdentityType::IDENTITY_TYPE_UNKNOWN,
15
15
  none: Aserto::Authorizer::V2::Api::IdentityType::IDENTITY_TYPE_NONE,
16
+ manual: Aserto::Authorizer::V2::Api::IdentityType::IDENTITY_TYPE_MANUAL,
16
17
  sub: Aserto::Authorizer::V2::Api::IdentityType::IDENTITY_TYPE_SUB,
17
18
  jwt: Aserto::Authorizer::V2::Api::IdentityType::IDENTITY_TYPE_JWT
18
19
  }.freeze
@@ -1,14 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "aserto/directory"
4
- require_relative "interceptors/headers"
5
- require_relative "requests"
3
+ require_relative "v2/client"
6
4
 
7
5
  module Aserto
8
6
  module Directory
9
7
  class Client
10
- include Requests
11
-
12
8
  # Creates a new Directory Client
13
9
  #
14
10
  # @param url [String] the gRpc url of the directory server
@@ -17,127 +13,28 @@ module Aserto
17
13
  # @param cert_path [String] the path to the certificates folder
18
14
  #
19
15
  # @return [Aserto::Directory::Client] the new Directory Client
20
- def initialize(url: "directory.prod.aserto.com:8443", api_key: nil, tenant_id: nil, cert_path: nil)
21
- @reader_client = ::Aserto::Directory::Reader::V2::Reader::Stub.new(
22
- url,
23
- load_creds(cert_path),
24
- interceptors: [Interceptors::Headers.new(api_key, tenant_id)]
25
- )
26
- @writer_client = ::Aserto::Directory::Writer::V2::Writer::Stub.new(
27
- url,
28
- load_creds(cert_path),
29
- interceptors: [Interceptors::Headers.new(api_key, tenant_id)]
30
- )
31
- end
32
-
33
- # Check permissions
34
- #
35
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
36
- # @param permission [String] permission name to be checked
37
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
38
- # @param trace [Boolean] whether to enable tracing
39
- #
40
- # @return [Boolean]
41
- def check_permission(subject:, permission:, object:, trace: false)
42
- reader_client.check_permission(check_permission_request(subject, permission, object, trace))
43
- end
44
-
45
- # Check relation
46
- #
47
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
48
- # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier] relation name to be checked
49
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
50
- # @param trace [Boolean] whether to enable tracing
51
- #
52
- # @return [Boolean]
53
- def check_relation(subject:, relation:, object:, trace: false)
54
- reader_client.check_relation(check_relation_request(subject, relation, object, trace))
55
- end
56
-
57
- # Get an object by type and key
58
- #
59
- # @param type [String] the type of object
60
- # @param key [String] the key of the object
61
- #
62
- # @return [::Aserto::Directory::Common::V2::Object]
63
- def object(type:, key:)
64
- reader_client.get_object(object_request(key, type)).result
65
- end
66
-
67
- # Set an object
68
- #
69
- # @param object [::Aserto::Directory::Common::V2::Object]
70
- #
71
- # @return [::Aserto::Directory::Common::V2::Object] the created/updated object
72
- def set_object(object:)
73
- writer_client.set_object(new_object_request(object)).result
74
- end
75
-
76
- # Get a list of objects by type
77
- #
78
- # @param type [String] the type of objects
79
- # @param page [::Aserto::Directory::Common::V2::PaginationRequest]
80
- #
81
- # @return [Array<::Aserto::Directory::Common::V2::Object>]
82
- def objects(type:, page: nil)
83
- reader_client.get_objects(objects_request(type, page)).results
84
- end
85
16
 
86
- # Get a relation
87
- #
88
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
89
- # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
90
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
91
- #
92
- # @return [::Aserto::Directory::Common::V2::Relation]
93
- def relation(subject: nil, relation: nil, object: nil)
94
- reader_client.get_relation(relation_request(subject, relation, object)).results
95
- end
17
+ def initialize(url: "directory.prod.aserto.com:8443", api_key: nil, tenant_id: nil, cert_path: nil)
18
+ warn WARN_MESSAGE
96
19
 
97
- # Get a list of relations
98
- #
99
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
100
- # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
101
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
102
- #
103
- # @return [Array<::Aserto::Directory::Common::V2::Relation>]
104
- def relations(subject: nil, relation: nil, object: nil, page: nil)
105
- reader_client.get_relations(relations_request(subject, relation, object, page)).results
20
+ @v2_client = Aserto::Directory::V2::Client.new(
21
+ url: url, api_key: api_key, tenant_id: tenant_id, cert_path: cert_path
22
+ )
106
23
  end
107
24
 
108
- # Set a relation
109
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
110
- # @param relation [String] name of the relation
111
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
112
- # @param hash [String] hash of the relation(required for updating a relation)
113
- #
114
- # @return [::Aserto::Directory::Common::V2::Relation] the created/updated relation
115
- def set_relation(subject:, relation:, object:, hash: nil)
116
- writer_client.set_relation(new_relation_request(subject, relation, object, hash)).result
25
+ def method_missing(method, args)
26
+ @v2_client.send(method, **args)
117
27
  end
118
28
 
119
- # Delete a relation
120
- #
121
- # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
122
- # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
123
- # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
124
- #
125
- # @return nil
126
- def delete_relation(subject:, relation:, object:)
127
- writer_client.delete_relation(delete_relation_request(subject, relation, object))
29
+ def respond_to_missing?(_name, _include_private)
30
+ true
128
31
  end
129
32
 
130
- private
131
-
132
- attr_reader :reader_client, :writer_client
133
-
134
- def load_creds(cert_path)
135
- if cert_path && File.file?(cert_path)
136
- GRPC::Core::ChannelCredentials.new(File.read(cert_path))
137
- else
138
- GRPC::Core::ChannelCredentials.new
139
- end
140
- end
33
+ WARN_MESSAGE = <<~TEXT
34
+ Aserto::Directory::Client is deprecated and will be removed.
35
+ Use Aserto::Directory::V3::Client for the latest Directory Client.
36
+ If you need Directory V2, use Aserto::Directory::V2::Client
37
+ TEXT
141
38
  end
142
39
  end
143
40
  end
@@ -10,11 +10,31 @@ module Aserto
10
10
  super()
11
11
  end
12
12
 
13
- def request_response(method:, request:, call:, metadata:)
13
+ def request_response(request: nil, call: nil, method: nil, metadata: nil)
14
+ update_metadata(metadata)
15
+ yield(request, call, method, metadata)
16
+ end
17
+
18
+ def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil)
19
+ update_metadata(metadata)
20
+ yield(requests, call, method, metadata)
21
+ end
22
+
23
+ def client_streamer(requests: nil, call: nil, method: nil, metadata: nil)
24
+ update_metadata(metadata)
25
+ yield(requests, call, method, metadata)
26
+ end
27
+
28
+ def server_streamer(request: nil, call: nil, method: nil, metadata: nil)
29
+ update_metadata(metadata)
30
+ yield(request, call, method, metadata)
31
+ end
32
+
33
+ private
34
+
35
+ def update_metadata(metadata)
14
36
  metadata["aserto-tenant-id"] = @tenant_id
15
37
  metadata["authorization"] = @api_key
16
-
17
- yield(method, request, call, metadata)
18
38
  end
19
39
  end
20
40
  end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aserto/directory"
4
+ require_relative "../interceptors/headers"
5
+ require_relative "requests"
6
+
7
+ module Aserto
8
+ module Directory
9
+ module V2
10
+ class Client
11
+ include Requests
12
+
13
+ # Creates a new Directory V2 Client
14
+ #
15
+ # @param url [String] the gRpc url of the directory server
16
+ # @param api_key [String] the api key of the directory server(for hosted directory)
17
+ # @param tenant_id [String] the tenant id of the directory server(for hosted directory)
18
+ # @param cert_path [String] the path to the certificates folder
19
+ #
20
+ # @return [Aserto::Directory::V2::Client] the new Directory Client
21
+ def initialize(url: "directory.prod.aserto.com:8443", api_key: nil, tenant_id: nil, cert_path: nil)
22
+ @reader_client = ::Aserto::Directory::Reader::V2::Reader::Stub.new(
23
+ url,
24
+ load_creds(cert_path),
25
+ interceptors: [Interceptors::Headers.new(api_key, tenant_id)]
26
+ )
27
+ @writer_client = ::Aserto::Directory::Writer::V2::Writer::Stub.new(
28
+ url,
29
+ load_creds(cert_path),
30
+ interceptors: [Interceptors::Headers.new(api_key, tenant_id)]
31
+ )
32
+ end
33
+
34
+ # Check permissions
35
+ #
36
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
37
+ # @param permission [String] permission name to be checked
38
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
39
+ # @param trace [Boolean] whether to enable tracing
40
+ #
41
+ # @return [Boolean]
42
+ def check_permission(subject:, permission:, object:, trace: false)
43
+ reader_client.check_permission(check_permission_request(subject, permission, object, trace))
44
+ end
45
+
46
+ # Check relation
47
+ #
48
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
49
+ # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier] relation name to be checked
50
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
51
+ # @param trace [Boolean] whether to enable tracing
52
+ #
53
+ # @return [Boolean]
54
+ def check_relation(subject:, relation:, object:, trace: false)
55
+ reader_client.check_relation(check_relation_request(subject, relation, object, trace))
56
+ end
57
+
58
+ # Get an object by type and key
59
+ #
60
+ # @param type [String] the type of object
61
+ # @param key [String] the key of the object
62
+ #
63
+ # @return [::Aserto::Directory::Common::V2::Object]
64
+ def object(type:, key:)
65
+ reader_client.get_object(object_request(key, type)).result
66
+ end
67
+
68
+ # Set an object
69
+ #
70
+ # @param object [::Aserto::Directory::Common::V2::Object]
71
+ #
72
+ # @return [::Aserto::Directory::Common::V2::Object] the created/updated object
73
+ def set_object(object:)
74
+ writer_client.set_object(new_object_request(object)).result
75
+ end
76
+
77
+ # Get a list of objects by type
78
+ #
79
+ # @param type [String] the type of objects
80
+ # @param page [::Aserto::Directory::Common::V2::PaginationRequest]
81
+ #
82
+ # @return [Array<::Aserto::Directory::Common::V2::Object>]
83
+ def objects(type:, page: nil)
84
+ reader_client.get_objects(objects_request(type, page)).results
85
+ end
86
+
87
+ # Get a relation
88
+ #
89
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
90
+ # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
91
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
92
+ #
93
+ # @return [::Aserto::Directory::Common::V2::Relation]
94
+ def relation(subject: nil, relation: nil, object: nil)
95
+ reader_client.get_relation(relation_request(subject, relation, object)).results
96
+ end
97
+
98
+ # Get a list of relations
99
+ #
100
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
101
+ # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
102
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
103
+ #
104
+ # @return [Array<::Aserto::Directory::Common::V2::Relation>]
105
+ def relations(subject: nil, relation: nil, object: nil, page: nil)
106
+ reader_client.get_relations(relations_request(subject, relation, object, page)).results
107
+ end
108
+
109
+ # Set a relation
110
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
111
+ # @param relation [String] name of the relation
112
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
113
+ # @param hash [String] hash of the relation(required for updating a relation)
114
+ #
115
+ # @return [::Aserto::Directory::Common::V2::Relation] the created/updated relation
116
+ def set_relation(subject:, relation:, object:, hash: nil)
117
+ writer_client.set_relation(new_relation_request(subject, relation, object, hash)).result
118
+ end
119
+
120
+ # Delete a relation
121
+ #
122
+ # @param subject [::Aserto::Directory::Common::V2::ObjectIdentifier]
123
+ # @param relation [::Aserto::Directory::Common::V2::RelationTypeIdentifier]
124
+ # @param object [::Aserto::Directory::Common::V2::ObjectIdentifier]
125
+ #
126
+ # @return nil
127
+ def delete_relation(subject:, relation:, object:)
128
+ writer_client.delete_relation(delete_relation_request(subject, relation, object))
129
+ end
130
+
131
+ private
132
+
133
+ attr_reader :reader_client, :writer_client
134
+
135
+ def load_creds(cert_path)
136
+ if cert_path && File.file?(cert_path)
137
+ GRPC::Core::ChannelCredentials.new(File.read(cert_path))
138
+ else
139
+ GRPC::Core::ChannelCredentials.new
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aserto/directory"
4
+ require_relative "../interceptors/headers"
5
+ require_relative "config"
6
+ require_relative "reader"
7
+ require_relative "writer"
8
+ require_relative "model"
9
+ require_relative "importer"
10
+ require_relative "exporter"
11
+
12
+ module Aserto
13
+ module Directory
14
+ module V3
15
+ class Client
16
+ extend Forwardable
17
+ include ::Aserto::Directory::V3::Reader
18
+ # @!parse include ::Aserto::Directory::V3::Reader
19
+
20
+ include ::Aserto::Directory::V3::Writer
21
+ # @!parse include ::Aserto::Directory::V3::Writer
22
+
23
+ include ::Aserto::Directory::V3::Model
24
+ # @!parse include ::Aserto::Directory::V3::Model
25
+
26
+ include ::Aserto::Directory::V3::Importer
27
+ # @!parse include ::Aserto::Directory::V3::Importer
28
+
29
+ include ::Aserto::Directory::V3::Exporter
30
+ # @!parse include ::Aserto::Directory::V3::Exporter
31
+
32
+ # Creates a new Directory V3 Client
33
+ #
34
+ # @param config [Aserto::Directory::V3::Config] the service configuration
35
+ # Base configuration
36
+ # If non-nil, this configuration is used for any client that doesn't have its own configuration.
37
+ # If nil, only clients that have their own configuration will be created.
38
+ #
39
+ # @example Create a new Directory V3 Client with all the services
40
+ # client = Aserto::Directory::V3::Client.new(
41
+ # {
42
+ # url: "directory.eng.aserto.com:8443",
43
+ # tenant_id: "tenant-id",
44
+ # api_key: "basic api-key",
45
+ # }
46
+ # )
47
+ #
48
+ # @example Create a new Directory V3 Client with reader only
49
+ # client = Aserto::Directory::V3::Client.new(
50
+ # {
51
+ # reader: {
52
+ # url: "directory.eng.aserto.com:8443",
53
+ # tenant_id: "tenant-id",
54
+ # api_key: "basic api-key",
55
+ # }
56
+ # }
57
+ # )
58
+ #
59
+ # @return [Aserto::Directory::V3::Client] the new Directory V3 Client
60
+ def initialize(config)
61
+ base_config = ::Aserto::Directory::V3::Config.new(config)
62
+
63
+ @reader = create_client(:reader, base_config.reader)
64
+ @writer = create_client(:writer, base_config.writer)
65
+ @importer = create_client(:importer, base_config.importer)
66
+ @exporter = create_client(:exporter, base_config.exporter)
67
+ @model = create_client(:model, base_config.model)
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :reader, :writer, :model, :importer, :exporter
73
+
74
+ class NullClient
75
+ def initialize(name)
76
+ @name = name
77
+ end
78
+
79
+ def method_missing(method, *_args)
80
+ puts "Cannot call '#{method}': '#{@name.to_s.capitalize}' client is not initialized."
81
+ end
82
+
83
+ def respond_to_missing?(_name, _include_private)
84
+ true
85
+ end
86
+ end
87
+
88
+ SERVICE_MAP = {
89
+ reader: ::Aserto::Directory::Reader::V3::Reader::Stub,
90
+ writer: ::Aserto::Directory::Writer::V3::Writer::Stub,
91
+ importer: ::Aserto::Directory::Importer::V3::Importer::Stub,
92
+ exporter: ::Aserto::Directory::Exporter::V3::Exporter::Stub,
93
+ model: ::Aserto::Directory::Model::V3::Model::Stub
94
+ }.freeze
95
+
96
+ def create_client(type, config)
97
+ return NullClient.new(type) unless config
98
+
99
+ SERVICE_MAP[type].new(
100
+ config.url,
101
+ config.credentials,
102
+ interceptors: config.interceptors
103
+ )
104
+ end
105
+ end
106
+
107
+ remove_const(:Reader)
108
+ remove_const(:Writer)
109
+ remove_const(:Model)
110
+ remove_const(:Importer)
111
+ remove_const(:Exporter)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../interceptors/headers"
4
+
5
+ module Aserto
6
+ module Directory
7
+ module V3
8
+ class Config
9
+ attr_reader :reader, :writer, :importer, :exporter, :model
10
+
11
+ def initialize(config)
12
+ @base = {
13
+ url: config[:url] || "directory.prod.aserto.com:8443",
14
+ api_key: config[:api_key],
15
+ tenant_id: config[:tenant_id],
16
+ cert_path: config[:cert_path]
17
+ }
18
+
19
+ @reader = build(**(config[:reader] || {}))
20
+ @writer = build(**(config[:writer] || {}))
21
+ @importer = build(**(config[:importer] || {}))
22
+ @exporter = build(**(config[:exporter] || {}))
23
+ @model = build(**(config[:model] || {}))
24
+ end
25
+
26
+ private
27
+
28
+ class BaseConfig
29
+ attr_reader :url, :credentials, :interceptors
30
+
31
+ def initialize(url, credentials, interceptors)
32
+ @url = url
33
+ @credentials = credentials
34
+ @interceptors = interceptors
35
+ end
36
+ end
37
+
38
+ def build(
39
+ url: @base[:url],
40
+ api_key: @base[:api_key],
41
+ tenant_id: @base[:tenant_id],
42
+ cert_path: @base[:cert_path]
43
+ )
44
+
45
+ interceptors = []
46
+ interceptors = [Interceptors::Headers.new(api_key, tenant_id)] if !api_key.nil? && !tenant_id.nil?
47
+ BaseConfig.new(url, load_creds(cert_path), interceptors)
48
+ end
49
+
50
+ def load_creds(cert_path)
51
+ if cert_path && File.file?(cert_path)
52
+ GRPC::Core::ChannelCredentials.new(File.read(cert_path))
53
+ else
54
+ GRPC::Core::ChannelCredentials.new
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module Directory
5
+ module V3
6
+ module Exporter
7
+ DATA_TYPE = {
8
+ unknown: ::Aserto::Directory::Exporter::V3::Option::OPTION_UNKNOWN,
9
+ objects: ::Aserto::Directory::Exporter::V3::Option::OPTION_DATA_OBJECTS,
10
+ relations: ::Aserto::Directory::Exporter::V3::Option::OPTION_DATA_RELATIONS,
11
+ all: ::Aserto::Directory::Exporter::V3::Option::OPTION_DATA
12
+ }.freeze
13
+
14
+ #
15
+ # Exports directory data
16
+ #
17
+ # @param [String] data_type one of [:unknown, :objects, :relations, :all]
18
+ #
19
+ def export(data_type: :unknown)
20
+ data = []
21
+ operation = exporter.export(
22
+ Aserto::Directory::Exporter::V3::ExportRequest.new(options: DATA_TYPE[data_type]),
23
+ return_op: true
24
+ )
25
+
26
+ response = operation.execute
27
+ response.each { |r| data.push(r) }
28
+ operation.wait
29
+
30
+ data
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module Directory
5
+ module V3
6
+ module Importer
7
+ #
8
+ # Imports objects and relations
9
+ #
10
+ # @param Array[Hash] data to be imported
11
+ #
12
+ # @example
13
+ # directory.import(
14
+ # [
15
+ # { object: { id: "import-user", type: "user" } },
16
+ # { object: { id: "import-group", type: "group" } },
17
+ # {
18
+ # relation: {
19
+ # object_id: "import-user",
20
+ # object_type: "user",
21
+ # relation: "member",
22
+ # subject_id: "import-group",
23
+ # subject_type: "group"
24
+ # }
25
+ # }
26
+ # ]
27
+ # )
28
+ def import(data)
29
+ data.map! do |value|
30
+ Aserto::Directory::Importer::V3::ImportRequest.new(value)
31
+ end
32
+ operation = importer.import(data, return_op: true)
33
+ response = operation.execute
34
+ response.each { |r| } # ensures that the server sends trailing data
35
+ operation.wait
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module Directory
5
+ module V3
6
+ module Model
7
+ # rubocop:disable Naming/AccessorMethodName
8
+
9
+ # Get the content of a manifest
10
+ # @return [Hash] { body: String, updated_at: Timestap, etag: String }
11
+ def get_manifest
12
+ response = {}
13
+ manifest_enum = @model.get_manifest(Aserto::Directory::Model::V3::GetManifestRequest.new)
14
+ manifest_enum.each do |resp|
15
+ response[:body] = resp.body.data if resp.respond_to?(:body) && !resp.body.nil?
16
+ if resp.respond_to?(:metadata)
17
+ response[:updated_at] ||= resp.metadata&.updated_at&.to_time
18
+ response[:etag] ||= resp.metadata&.etag
19
+ end
20
+ end
21
+
22
+ response
23
+ end
24
+
25
+ # Set the content of a manifest
26
+ # @param body [String]
27
+ # @return [Aserto::Directory::Model::V3::SetManifestResponse]
28
+ def set_manifest(body)
29
+ @model.set_manifest([Aserto::Directory::Model::V3::SetManifestRequest.new(body: { data: body })])
30
+ end
31
+
32
+ # rubocop:enable Naming/AccessorMethodName
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,266 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module Directory
5
+ module V3
6
+ module Reader
7
+ #
8
+ # find an object by id and type
9
+ #
10
+ # @param object_id [String]
11
+ # @param object_type [String]
12
+ #
13
+ # @return [Aserto::Directory::Reader::V3::GetObjectResponse]
14
+ #
15
+ # @example
16
+ # client.get_object(
17
+ # object_type: "user",
18
+ # object_id: "rick@the-citadel.com"
19
+ # )
20
+ def get_object(object_id:, object_type:)
21
+ reader.get_object(
22
+ Aserto::Directory::Reader::V3::GetObjectRequest.new(
23
+ object_id: object_id,
24
+ object_type: object_type
25
+ )
26
+ )
27
+ end
28
+
29
+ #
30
+ # list objects by type
31
+ #
32
+ # @param object_type [String]
33
+ # @param page [Hash]
34
+ # @option page [Integer] :size
35
+ # @option page [String] :token
36
+ #
37
+ # @return [Aserto::Directory::V3::GetObjectsResponse]
38
+ #
39
+ # @example
40
+ # client.get_objects(
41
+ # object_type: "user",
42
+ # page: { size: 2 }
43
+ # )
44
+ def get_objects(object_type:, page: { size: 100 })
45
+ reader.get_objects(
46
+ Aserto::Directory::Reader::V3::GetObjectsRequest.new(
47
+ object_type: object_type,
48
+ page: Aserto::Directory::Common::V3::PaginationRequest.new(page)
49
+ )
50
+ )
51
+ end
52
+
53
+ #
54
+ # find a relation between two objects
55
+ #
56
+ # @param [String] object_type
57
+ # @param [String] object_id
58
+ # @param [String] relation
59
+ # @param [String] subject_type
60
+ # @param [String] subject_id
61
+ # @param [String] subject_relation
62
+ # @param [Boolean] with_objects
63
+ #
64
+ # @return [Aserto::Directory::Reader::V3::GetRelationResponse]
65
+ #
66
+ # @example
67
+ # client.get_relation(
68
+ # object_type: "user",
69
+ # object_id: "rick@the-citadel.com",
70
+ # relation: "member",
71
+ # object_type: "group",
72
+ # object_id: "evil_genius"
73
+ # )
74
+ def get_relation(object_type:, object_id:, relation:, subject_type:, subject_id:, subject_relation: "",
75
+ with_objects: false)
76
+ reader.get_relation(
77
+ Aserto::Directory::Reader::V3::GetRelationRequest.new(
78
+ object_type: object_type,
79
+ object_id: object_id,
80
+ relation: relation,
81
+ subject_type: subject_type,
82
+ subject_id: subject_id,
83
+ subject_relation: subject_relation,
84
+ with_objects: with_objects
85
+ )
86
+ )
87
+ end
88
+
89
+ #
90
+ # List relations between two objects
91
+ #
92
+ # @param [String] object_type
93
+ # @param [String] object_id
94
+ # @param [String] relation
95
+ # @param [String] subject_type
96
+ # @param [String] subject_id
97
+ # @param [String] subject_relation
98
+ # @param [Boolean] with_objects
99
+ # @param page [Hash]
100
+ # @option page [Integer] :size
101
+ # @option page [String] :token
102
+ #
103
+ # @return [Aserto::Directory::Reader::V3::GetRelationsResponse]
104
+ #
105
+ # @example
106
+ # client.get_relations(
107
+ # object_type: "user",
108
+ # object_id: "rick@the-citadel.com",
109
+ # relation: "member",
110
+ # page: { size: 10 }
111
+ # )
112
+ def get_relations(object_type: "", object_id: "", relation: "", subject_type: "", subject_id: "",
113
+ subject_relation: "", with_objects: false, page: { size: 100 })
114
+ reader.get_relations(
115
+ Aserto::Directory::Reader::V3::GetRelationsRequest.new(
116
+ object_type: object_type,
117
+ object_id: object_id,
118
+ relation: relation,
119
+ subject_type: subject_type,
120
+ subject_id: subject_id,
121
+ subject_relation: subject_relation,
122
+ with_objects: with_objects,
123
+ page: Aserto::Directory::Common::V3::PaginationRequest.new(page)
124
+ )
125
+ )
126
+ end
127
+
128
+ #
129
+ # Check relation between two objects
130
+ #
131
+ # @param [String] object_type
132
+ # @param [String] object_id
133
+ # @param [String] relation
134
+ # @param [String] subject_type
135
+ # @param [String] subject_id
136
+ # @param [Boolean] trace
137
+ #
138
+ # @return [Aserto::Directory::Reader::V3::CheckRelationResponse]
139
+ #
140
+ # @example
141
+ # client.check_relation(
142
+ # object_type: "user",
143
+ # object_id: "rick@the-citadel.com",
144
+ # relation: "member",
145
+ # object_type: "group",
146
+ # object_id: "evil_genius"
147
+ # )
148
+ def check_relation(object_type:, object_id:, relation:, subject_type:, subject_id:, trace: false)
149
+ reader.check_relation(
150
+ Aserto::Directory::Reader::V3::CheckRelationRequest.new(
151
+ object_type: object_type,
152
+ object_id: object_id,
153
+ relation: relation,
154
+ subject_type: subject_type,
155
+ subject_id: subject_id,
156
+ trace: trace
157
+ )
158
+ )
159
+ end
160
+
161
+ #
162
+ # Check relation between two objects
163
+ #
164
+ # @param [String] object_type
165
+ # @param [String] object_id
166
+ # @param [String] relation
167
+ # @param [String] subject_type
168
+ # @param [String] subject_id
169
+ # @param [Boolean] trace
170
+ #
171
+ # @return [Aserto::Directory::Reader::V3::CheckResponse]
172
+ #
173
+ # @example
174
+ # client.check(
175
+ # object_type: "user",
176
+ # object_id: "rick@the-citadel.com",
177
+ # relation: "member",
178
+ # object_type: "group",
179
+ # object_id: "evil_genius"
180
+ # )
181
+ def check(object_type:, object_id:, relation:, subject_type:, subject_id:, trace: false)
182
+ reader.check(
183
+ Aserto::Directory::Reader::V3::CheckRequest.new(
184
+ object_type: object_type,
185
+ object_id: object_id,
186
+ relation: relation,
187
+ subject_type: subject_type,
188
+ subject_id: subject_id,
189
+ trace: trace
190
+ )
191
+ )
192
+ end
193
+
194
+ #
195
+ # Check permission between two objects
196
+ #
197
+ # @param [String] object_type
198
+ # @param [String] object_id
199
+ # @param [String] permission
200
+ # @param [String] subject_type
201
+ # @param [String] subject_id
202
+ # @param [Boolean] trace
203
+ #
204
+ # @return [Aserto::Directory::Reader::V3::CheckPermissionResponse]
205
+ #
206
+ # @example
207
+ # client.check_permission(
208
+ # object_type: "user",
209
+ # object_id: "rick@the-citadel.com",
210
+ # permission: "read",
211
+ # object_type: "group",
212
+ # object_id: "evil_genius"
213
+ # )
214
+ def check_permission(object_type:, object_id:, permission:, subject_type:, subject_id:, trace: false)
215
+ reader.check_permission(
216
+ Aserto::Directory::Reader::V3::CheckPermissionRequest.new(
217
+ object_type: object_type,
218
+ object_id: object_id,
219
+ permission: permission,
220
+ subject_type: subject_type,
221
+ subject_id: subject_id,
222
+ trace: trace
223
+ )
224
+ )
225
+ end
226
+
227
+ #
228
+ # Returns object graph from anchor to subject or object.
229
+ #
230
+ # @param [String] anchor_type <description>
231
+ # @param [String] anchor_id <description>
232
+ # @param [String] object_type <description>
233
+ # @param [String] object_id <description>
234
+ # @param [String] relation <description>
235
+ # @param [String] subject_type <description>
236
+ # @param [String] <description>
237
+ #
238
+ # @return [Aserto::Directory::Reader::V3::GetGraphResponse]
239
+ #
240
+ # @example
241
+ # directory.get_graph(
242
+ # anchor_type: "user",
243
+ # anchor_id: "rick@the-citadel.com",
244
+ # subject_id: "rick@the-citadel.com",
245
+ # subject_type: "user",
246
+ # relation: "member"
247
+ # )
248
+ def get_graph(anchor_type:, anchor_id:, object_type: "", object_id: "", relation: "", subject_type: "",
249
+ subject_id: "", subject_relation: "")
250
+ reader.get_graph(
251
+ Aserto::Directory::Reader::V3::GetGraphRequest.new(
252
+ anchor_type: anchor_type,
253
+ anchor_id: anchor_id,
254
+ object_type: object_type,
255
+ object_id: object_id,
256
+ relation: relation,
257
+ subject_type: subject_type,
258
+ subject_id: subject_id,
259
+ subject_relation: subject_relation
260
+ )
261
+ )
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module Directory
5
+ module V3
6
+ module Writer
7
+ require "google/protobuf/well_known_types"
8
+
9
+ #
10
+ # Create a new object
11
+ #
12
+ # @param [String] object_id
13
+ # @param [String] object_type
14
+ # @param [String] display_name
15
+ # @param [Hash] properties
16
+ # @param [String] etag
17
+ #
18
+ # @return [Aserto::Directory::Writer::V3::SetObjectResponse]
19
+ #
20
+ # @example
21
+ # client.set_object(object_id: "1234", object_type: "user", properties: { email: "test" })
22
+ def set_object(object_id:, object_type:, display_name: "", properties: {}, etag: nil)
23
+ writer.set_object(
24
+ Aserto::Directory::Writer::V3::SetObjectRequest.new(
25
+ object: {
26
+ id: object_id,
27
+ type: object_type,
28
+ display_name: display_name,
29
+ properties: Google::Protobuf::Struct.from_hash(properties.transform_keys!(&:to_s)),
30
+ etag: etag
31
+ }
32
+ )
33
+ )
34
+ end
35
+
36
+ #
37
+ # Delete an object
38
+ #
39
+ # @param [String] object_id
40
+ # @param [String] object_type
41
+ # @param [Boolean] with_relations
42
+ #
43
+ # @return [ Aserto::Directory::Writer::V3::DeleteObjectResponse]
44
+ #
45
+ # @example
46
+ # client.delete_object(object_id: "1234", object_type: "user")
47
+ def delete_object(object_id:, object_type:, with_relations: false)
48
+ writer.delete_object(
49
+ Aserto::Directory::Writer::V3::DeleteObjectRequest.new(
50
+ object_id: object_id,
51
+ object_type: object_type,
52
+ with_relations: with_relations
53
+ )
54
+ )
55
+ end
56
+
57
+ #
58
+ # Creates a relation between two objects
59
+ #
60
+ # @param [String] object_type
61
+ # @param [String] object_id
62
+ # @param [String] relation
63
+ # @param [String] subject_type
64
+ # @param [String] subject_id
65
+ #
66
+ # @return [Aserto::Directory::Writer::V3::SetRelationResponse]
67
+ #
68
+ # @example
69
+ # client.set_relation(
70
+ # object_type: "user",
71
+ # object_id: "rick@the-citadel.com",
72
+ # relation: "member",
73
+ # object_type: "group",
74
+ # object_id: "evil_genius"
75
+ # )
76
+ def set_relation(object_type:, object_id:, relation:, subject_type:, subject_id:)
77
+ writer.set_relation(
78
+ Aserto::Directory::Writer::V3::SetRelationRequest.new(
79
+ relation: {
80
+ object_type: object_type,
81
+ object_id: object_id,
82
+ relation: relation,
83
+ subject_type: subject_type,
84
+ subject_id: subject_id
85
+ }
86
+ )
87
+ )
88
+ end
89
+
90
+ #
91
+ # Delete a relation between two objects
92
+ #
93
+ # @param [String] object_type
94
+ # @param [String] object_id
95
+ # @param [String] relation
96
+ # @param [String] subject_type
97
+ # @param [String] subject_id
98
+ # @param [String] subject_relation
99
+ #
100
+ # @return [Aserto::Directory::Writer::V3::DeleteRelationRequest]
101
+ #
102
+ # @example
103
+ # client.get_relation(
104
+ # object_type: "user",
105
+ # object_id: "rick@the-citadel.com",
106
+ # relation: "member",
107
+ # object_type: "group",
108
+ # object_id: "evil_genius"
109
+ # )
110
+ def delete_relation(object_type:, object_id:, relation:, subject_type:, subject_id:, subject_relation: "")
111
+ writer.delete_relation(
112
+ Aserto::Directory::Writer::V3::DeleteRelationRequest.new(
113
+ object_type: object_type,
114
+ object_id: object_id,
115
+ relation: relation,
116
+ subject_type: subject_type,
117
+ subject_id: subject_id,
118
+ subject_relation: subject_relation
119
+ )
120
+ )
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
data/lib/aserto/errors.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  module Aserto
4
4
  class Error < StandardError; end
5
5
  class InvalidResourceMapping < Error; end
6
+ class InvalidIdentityType < Error; end
6
7
 
7
8
  class AccessDenied < Error
8
9
  attr_reader :action, :conditions
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aserto
4
+ module IdentityMapper
5
+ module Manual
6
+ class << self
7
+ def execute(_request)
8
+ {
9
+ type: :manual,
10
+ identity: ::Aserto.config.identity_mapping[:value].to_s
11
+ }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -4,20 +4,23 @@ require_relative "identity_mapper/base"
4
4
  require_relative "identity_mapper/none"
5
5
  require_relative "identity_mapper/sub"
6
6
  require_relative "identity_mapper/jwt"
7
+ require_relative "identity_mapper/manual"
7
8
 
8
9
  module Aserto
9
10
  module IdentityMapper
10
11
  STRATEGY = {
11
12
  none: Aserto::IdentityMapper::None,
13
+ manual: Aserto::IdentityMapper::Manual,
12
14
  sub: Aserto::IdentityMapper::Sub,
13
15
  jwt: Aserto::IdentityMapper::Jwt
14
16
  }.freeze
15
17
 
16
18
  class << self
17
19
  def execute(request)
18
- STRATEGY[
19
- Aserto.config.identity_mapping[:type].to_sym || :none
20
- ].execute(request)
20
+ STRATEGY.fetch(
21
+ Aserto.config.identity_mapping[:type].to_sym || :none,
22
+ Aserto::IdentityMapper::None
23
+ ).execute(request)
21
24
  end
22
25
  end
23
26
  end
data/lib/aserto.rb CHANGED
@@ -12,6 +12,7 @@ require_relative "aserto/resource_mapper"
12
12
  require_relative "aserto/auth_client"
13
13
  require_relative "aserto/errors"
14
14
  require_relative "aserto/directory/client"
15
+ require_relative "aserto/directory/v3/client"
15
16
 
16
17
  module Aserto
17
18
  class << self
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aserto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.6
4
+ version: 0.30.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aserto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-24 00:00:00.000000000 Z
11
+ date: 2023-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aserto-authorizer
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.30.0
33
+ version: 0.30.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.30.0
40
+ version: 0.30.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: jwt
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -82,11 +82,20 @@ files:
82
82
  - lib/aserto/config.rb
83
83
  - lib/aserto/directory/client.rb
84
84
  - lib/aserto/directory/interceptors/headers.rb
85
- - lib/aserto/directory/requests.rb
85
+ - lib/aserto/directory/v2/client.rb
86
+ - lib/aserto/directory/v2/requests.rb
87
+ - lib/aserto/directory/v3/client.rb
88
+ - lib/aserto/directory/v3/config.rb
89
+ - lib/aserto/directory/v3/exporter.rb
90
+ - lib/aserto/directory/v3/importer.rb
91
+ - lib/aserto/directory/v3/model.rb
92
+ - lib/aserto/directory/v3/reader.rb
93
+ - lib/aserto/directory/v3/writer.rb
86
94
  - lib/aserto/errors.rb
87
95
  - lib/aserto/identity_mapper.rb
88
96
  - lib/aserto/identity_mapper/base.rb
89
97
  - lib/aserto/identity_mapper/jwt.rb
98
+ - lib/aserto/identity_mapper/manual.rb
90
99
  - lib/aserto/identity_mapper/none.rb
91
100
  - lib/aserto/identity_mapper/sub.rb
92
101
  - lib/aserto/policy_path_mapper.rb