keycloak-admin 0.7.0 → 0.7.1
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 +4 -4
- data/.gitignore +2 -1
- data/CHANGELOG.md +48 -0
- data/Gemfile.lock +1 -1
- data/README.md +109 -2
- data/lib/keycloak-admin.rb +9 -0
- data/lib/keycloak-admin/client/client.rb +11 -3
- data/lib/keycloak-admin/client/client_client.rb +24 -0
- data/lib/keycloak-admin/client/client_role_mappings_client.rb +20 -0
- data/lib/keycloak-admin/client/group_client.rb +46 -0
- data/lib/keycloak-admin/client/realm_client.rb +50 -0
- data/lib/keycloak-admin/client/role_client.rb +32 -0
- data/lib/keycloak-admin/client/user_client.rb +9 -2
- data/lib/keycloak-admin/representation/camel_json.rb +1 -1
- data/lib/keycloak-admin/representation/client_representation.rb +16 -0
- data/lib/keycloak-admin/representation/group_representation.rb +15 -0
- data/lib/keycloak-admin/representation/realm_representation.rb +14 -0
- data/lib/keycloak-admin/representation/representation.rb +4 -0
- data/lib/keycloak-admin/representation/role_representation.rb +17 -0
- data/lib/keycloak-admin/representation/user_representation.rb +13 -13
- data/lib/keycloak-admin/resource/user_resource.rb +18 -0
- data/lib/keycloak-admin/version.rb +1 -1
- data/spec/client/client_client_spec.rb +53 -0
- data/spec/client/client_role_mappings_client_spec.rb +48 -0
- data/spec/client/group_client_spec.rb +125 -0
- data/spec/client/realm_client_spec.rb +108 -0
- data/spec/client/role_client_spec.rb +83 -0
- data/spec/client/user_client_spec.rb +105 -14
- data/spec/representation/user_representation_spec.rb +15 -0
- data/spec/resource/user_resource_spec.rb +14 -0
- data/spec/spec_helper.rb +7 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39322dd0c0035b30a67644fa401bbe55c835dbf1
|
4
|
+
data.tar.gz: 268b16b6d6e20aac7a44ba993a76114f8d86e1b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f57fe6316a4378bfc8e3c90e6732b5977fc2f14a7871f0b69fb2790bcf60ec047a4a3841e8075eabfdd83d3961d3f1c4bdc38ac2a13a630e8a236e098d877bd
|
7
|
+
data.tar.gz: bb2384c3c9c16d498baade9a2ef02766396ca370724114da3b0136976bca61f6a9a6912d106ef5420f3bbdba65f06c88daa476088e77f28c2eaa73546857e1f6
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.7.1] - Next version
|
9
|
+
|
10
|
+
Thanks to @vlad-ro:
|
11
|
+
|
12
|
+
* List users
|
13
|
+
* List clients
|
14
|
+
* List groups, create/save a group
|
15
|
+
* List roles, save a role
|
16
|
+
* List realms, save/update/delete a realm
|
17
|
+
* Get list of client role mappings for a user
|
18
|
+
* Support passing rest client options for user save and search
|
19
|
+
* Support using gem without ActiveSupport
|
20
|
+
|
21
|
+
## [0.7.0] - 2019-06-11
|
22
|
+
|
23
|
+
Thanks to @vlad-ro:
|
24
|
+
|
25
|
+
* Support passing rest client options
|
26
|
+
* More documentation
|
27
|
+
* More tests
|
28
|
+
* Better handling of timeouts
|
29
|
+
|
30
|
+
## [0.6.5] - 2019-05-14
|
31
|
+
|
32
|
+
* Get user
|
33
|
+
|
34
|
+
## [0.6.2] - 2019-05-14
|
35
|
+
|
36
|
+
* Update users
|
37
|
+
|
38
|
+
## [0.6] - 2019-03-06
|
39
|
+
|
40
|
+
* Save a locale when creating a new user
|
41
|
+
|
42
|
+
## [0.5] - 2018-01-26
|
43
|
+
|
44
|
+
* Client to access Custom REST API configurable-token
|
45
|
+
|
46
|
+
## [0.3] - 2018-01-19
|
47
|
+
|
48
|
+
* Support of impersonation
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -58,6 +58,7 @@ KeycloakAdmin.configure do |config|
|
|
58
58
|
config.username = ENV["KEYCLOAK_ADMIN_USER"]
|
59
59
|
config.password = ENV["KEYCLOAK_ADMIN_PASSWORD"]
|
60
60
|
config.logger = Rails.logger
|
61
|
+
config.rest_client_options = { verify_ssl: OpenSSL::SSL::VERIFY_NONE }
|
61
62
|
end
|
62
63
|
```
|
63
64
|
This example is autoloaded in a Rails environment.
|
@@ -76,6 +77,7 @@ All options have a default value. However, all of them can be changed in your in
|
|
76
77
|
| `username` | `nil`| String | Optional | Username to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `mummy` |
|
77
78
|
| `password` | `nil`| String | Optional | Clear password to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `bobby` |
|
78
79
|
| `logger` | `Logger.new(STDOUT)`| Logger | Optional | The logger used by `keycloak-admin` | `Rails.logger` |
|
80
|
+
| `rest_client_options` | `{}`| Hash | Optional | Options to pass to `RestClient` | `{ verify_ssl: OpenSSL::SSL::VERIFY_NONE }` |
|
79
81
|
|
80
82
|
|
81
83
|
## Use Case
|
@@ -83,11 +85,16 @@ All options have a default value. However, all of them can be changed in your in
|
|
83
85
|
### Supported features
|
84
86
|
|
85
87
|
* Get an access token
|
86
|
-
* Create/update/get a user
|
88
|
+
* Create/update/get/delete a user
|
89
|
+
* Get list of users, search for user(s)
|
87
90
|
* Reset credentials
|
88
|
-
* Delete a user
|
89
91
|
* Impersonate a user
|
90
92
|
* Exchange a configurable token
|
93
|
+
* Get list of clients
|
94
|
+
* Get list of groups, create/save a group
|
95
|
+
* Get list of roles, save a role
|
96
|
+
* Get list of realms, save/update/delete a realm
|
97
|
+
* Get list of client role mappings for a user
|
91
98
|
|
92
99
|
### Get an access token
|
93
100
|
|
@@ -114,6 +121,14 @@ Returns an array of `KeycloakAdmin::UserRepresentation`.
|
|
114
121
|
KeycloakAdmin.realm("a_realm").users.search("a_username_or_an_email")
|
115
122
|
```
|
116
123
|
|
124
|
+
### List all users in a realm
|
125
|
+
|
126
|
+
Returns an array of `KeycloakAdmin::UserRepresentation`.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
KeycloakAdmin.realm("a_realm").users.list
|
130
|
+
```
|
131
|
+
|
117
132
|
### Save a user
|
118
133
|
|
119
134
|
Returns the provided `user`, which must be of type `KeycloakAdmin::UserRepresentation`.
|
@@ -188,6 +203,98 @@ token_lifespan_in_seconds = 20
|
|
188
203
|
KeycloakAdmin.realm("a_realm").configurable_token.exchange_with(user_access_token, token_lifespan_in_seconds)
|
189
204
|
```
|
190
205
|
|
206
|
+
### Get list of realms
|
207
|
+
|
208
|
+
Returns an array of `KeycloakAdmin::RealmRepresentation`.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
KeycloakAdmin.realm("master").list
|
212
|
+
```
|
213
|
+
|
214
|
+
### Save a realm
|
215
|
+
|
216
|
+
Takes `realm` of type `KeycloakAdmin::RealmRepresentation`, or an object implementing `to_json`, such as a `Hash`.
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
KeycloakAdmin.realm(nil).save(realm)
|
220
|
+
```
|
221
|
+
|
222
|
+
### Update a realm
|
223
|
+
|
224
|
+
If you want to update its entire entity. To update some specific attributes, provide an object implementing `to_json`, such as a `Hash`.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
KeycloakAdmin.realm("a_realm").update({
|
228
|
+
smtpServer: { host: 'test_host' }
|
229
|
+
})
|
230
|
+
```
|
231
|
+
|
232
|
+
### Delete a realm
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
KeycloakAdmin.realm("a_realm").delete
|
236
|
+
```
|
237
|
+
|
238
|
+
### Get list of clients in a realm
|
239
|
+
|
240
|
+
Returns an array of `KeycloakAdmin::ClientRepresentation`.
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
KeycloakAdmin.realm("a_realm").clients.list
|
244
|
+
```
|
245
|
+
|
246
|
+
### Get list of groups in a realm
|
247
|
+
|
248
|
+
Returns an array of `KeycloakAdmin::GroupRepresentation`.
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
KeycloakAdmin.realm("a_realm").groups.list
|
252
|
+
```
|
253
|
+
|
254
|
+
### Save a group
|
255
|
+
|
256
|
+
Returns the id of saved `group` provided, which must be of type `KeycloakAdmin::GroupRepresentation`.
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
KeycloakAdmin.realm("a_realm").groups.save(group)
|
260
|
+
```
|
261
|
+
|
262
|
+
### Create and save a group with a name and path
|
263
|
+
|
264
|
+
Returns the id of created group.
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
group_name = "test"
|
268
|
+
group_path = "/top"
|
269
|
+
group_id = KeycloakAdmin.realm("a_realm").groups.create!(group_name, group_path)
|
270
|
+
```
|
271
|
+
|
272
|
+
### Get list of roles in a realm
|
273
|
+
|
274
|
+
Returns an array of `KeycloakAdmin::RoleRepresentation`.
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
KeycloakAdmin.realm("a_realm").roles.list
|
278
|
+
```
|
279
|
+
|
280
|
+
### Save a role
|
281
|
+
|
282
|
+
Takes `role`, which must be of type `KeycloakAdmin::RoleRepresentation`.
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
KeycloakAdmin.realm("a_realm").roles.save(role)
|
286
|
+
```
|
287
|
+
|
288
|
+
### Get list of client role mappings for a user
|
289
|
+
|
290
|
+
Returns an array of `KeycloakAdmin::RoleRepresentation`.
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
user_id = "95985b21-d884-4bbd-b852-cb8cd365afc2"
|
294
|
+
client_id = "1869e876-71b4-4de2-849e-66540db3a098"
|
295
|
+
KeycloakAdmin.realm("a_realm").user(user_id).client_role_mappings(client_id).list_available
|
296
|
+
```
|
297
|
+
|
191
298
|
## How to execute library tests
|
192
299
|
|
193
300
|
From the `keycloak-admin-api` directory:
|
data/lib/keycloak-admin.rb
CHANGED
@@ -2,17 +2,26 @@ require "logger"
|
|
2
2
|
|
3
3
|
require_relative "keycloak-admin/configuration"
|
4
4
|
require_relative "keycloak-admin/client/client"
|
5
|
+
require_relative "keycloak-admin/client/client_client"
|
6
|
+
require_relative "keycloak-admin/client/client_role_mappings_client"
|
7
|
+
require_relative "keycloak-admin/client/group_client"
|
5
8
|
require_relative "keycloak-admin/client/realm_client"
|
9
|
+
require_relative "keycloak-admin/client/role_client"
|
6
10
|
require_relative "keycloak-admin/client/token_client"
|
7
11
|
require_relative "keycloak-admin/client/user_client"
|
8
12
|
require_relative "keycloak-admin/client/configurable_token_client"
|
9
13
|
require_relative "keycloak-admin/representation/camel_json"
|
10
14
|
require_relative "keycloak-admin/representation/representation"
|
15
|
+
require_relative "keycloak-admin/representation/client_representation"
|
16
|
+
require_relative "keycloak-admin/representation/group_representation"
|
11
17
|
require_relative "keycloak-admin/representation/token_representation"
|
12
18
|
require_relative "keycloak-admin/representation/impersonation_redirection_representation"
|
13
19
|
require_relative "keycloak-admin/representation/impersonation_representation"
|
14
20
|
require_relative "keycloak-admin/representation/credential_representation"
|
21
|
+
require_relative "keycloak-admin/representation/realm_representation"
|
22
|
+
require_relative "keycloak-admin/representation/role_representation"
|
15
23
|
require_relative "keycloak-admin/representation/user_representation"
|
24
|
+
require_relative "keycloak-admin/resource/user_resource"
|
16
25
|
|
17
26
|
module KeycloakAdmin
|
18
27
|
|
@@ -9,13 +9,13 @@ module KeycloakAdmin
|
|
9
9
|
@configuration.server_url
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
@
|
12
|
+
def current_token
|
13
|
+
@current_token ||= KeycloakAdmin.realm(@configuration.client_realm_name).token.get
|
14
14
|
end
|
15
15
|
|
16
16
|
def headers
|
17
17
|
{
|
18
|
-
Authorization: "Bearer #{
|
18
|
+
Authorization: "Bearer #{current_token.access_token}",
|
19
19
|
content_type: :json,
|
20
20
|
accept: :json
|
21
21
|
}
|
@@ -29,6 +29,14 @@ module KeycloakAdmin
|
|
29
29
|
http_error(e.response)
|
30
30
|
end
|
31
31
|
|
32
|
+
def created_id(response)
|
33
|
+
unless response.net_http_res.is_a? Net::HTTPCreated
|
34
|
+
raise "Create method returned status #{response.net_http_res.message} (Code: #{response.net_http_res.code}); expected status: Created (201)"
|
35
|
+
end
|
36
|
+
(_head, _separator, id) = response.headers[:location].rpartition('/')
|
37
|
+
id
|
38
|
+
end
|
39
|
+
|
32
40
|
private
|
33
41
|
|
34
42
|
def http_error(response)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module KeycloakAdmin
|
2
|
+
class ClientClient < Client
|
3
|
+
def initialize(configuration, realm_client)
|
4
|
+
super(configuration)
|
5
|
+
raise ArgumentError.new("realm must be defined") unless realm_client.name_defined?
|
6
|
+
@realm_client = realm_client
|
7
|
+
end
|
8
|
+
|
9
|
+
def list
|
10
|
+
response = execute_http do
|
11
|
+
RestClient::Resource.new(clients_url, @configuration.rest_client_options).get(headers)
|
12
|
+
end
|
13
|
+
JSON.parse(response).map { |client_as_hash| ClientRepresentation.from_hash(client_as_hash) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def clients_url(id=nil)
|
17
|
+
if id
|
18
|
+
"#{@realm_client.realm_admin_url}/clients/#{id}"
|
19
|
+
else
|
20
|
+
"#{@realm_client.realm_admin_url}/clients"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module KeycloakAdmin
|
2
|
+
class ClientRoleMappingsClient < Client
|
3
|
+
def initialize(configuration, user_resource, client_id)
|
4
|
+
super(configuration)
|
5
|
+
@user_resource = user_resource
|
6
|
+
@client_id = client_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def list_available
|
10
|
+
response = execute_http do
|
11
|
+
RestClient::Resource.new(list_available_url, @configuration.rest_client_options).get(headers)
|
12
|
+
end
|
13
|
+
JSON.parse(response).map { |role_as_hash| RoleRepresentation.from_hash(role_as_hash) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def list_available_url
|
17
|
+
"#{@user_resource.resource_url}/role-mappings/clients/#{@client_id}/available"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module KeycloakAdmin
|
2
|
+
class GroupClient < Client
|
3
|
+
def initialize(configuration, realm_client)
|
4
|
+
super(configuration)
|
5
|
+
raise ArgumentError.new("realm must be defined") unless realm_client.name_defined?
|
6
|
+
@realm_client = realm_client
|
7
|
+
end
|
8
|
+
|
9
|
+
def list
|
10
|
+
response = execute_http do
|
11
|
+
RestClient::Resource.new(groups_url, @configuration.rest_client_options).get(headers)
|
12
|
+
end
|
13
|
+
JSON.parse(response).map { |group_as_hash| GroupRepresentation.from_hash(group_as_hash) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def create!(name, path = nil)
|
17
|
+
response = save(build(name, path))
|
18
|
+
created_id(response)
|
19
|
+
end
|
20
|
+
|
21
|
+
def save(group_representation)
|
22
|
+
execute_http do
|
23
|
+
RestClient::Resource.new(groups_url, @configuration.rest_client_options).post(
|
24
|
+
group_representation.to_json, headers
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def groups_url(id=nil)
|
30
|
+
if id
|
31
|
+
"#{@realm_client.realm_admin_url}/groups/#{id}"
|
32
|
+
else
|
33
|
+
"#{@realm_client.realm_admin_url}/groups"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def build(name, path)
|
40
|
+
group = GroupRepresentation.new
|
41
|
+
group.name = name
|
42
|
+
group.path = path
|
43
|
+
group
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -5,6 +5,36 @@ module KeycloakAdmin
|
|
5
5
|
@realm_name = realm_name
|
6
6
|
end
|
7
7
|
|
8
|
+
def list
|
9
|
+
response = execute_http do
|
10
|
+
RestClient::Resource.new(realm_list_url, @configuration.rest_client_options).get(headers)
|
11
|
+
end
|
12
|
+
JSON.parse(response).map { |realm_as_hash| RealmRepresentation.from_hash(realm_as_hash) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete
|
16
|
+
execute_http do
|
17
|
+
RestClient::Resource.new(realm_admin_url, @configuration.rest_client_options).delete(headers)
|
18
|
+
end
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def save(realm_representation)
|
23
|
+
execute_http do
|
24
|
+
RestClient::Resource.new(realm_list_url, @configuration.rest_client_options).post(
|
25
|
+
realm_representation.to_json, headers
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def update(realm_representation_body)
|
31
|
+
execute_http do
|
32
|
+
RestClient::Resource.new(realm_admin_url, @configuration.rest_client_options).put(
|
33
|
+
realm_representation_body.to_json, headers
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
8
38
|
def realm_url
|
9
39
|
if @realm_name
|
10
40
|
"#{server_url}/realms/#{@realm_name}"
|
@@ -21,6 +51,10 @@ module KeycloakAdmin
|
|
21
51
|
end
|
22
52
|
end
|
23
53
|
|
54
|
+
def realm_list_url
|
55
|
+
"#{server_url}/admin/realms"
|
56
|
+
end
|
57
|
+
|
24
58
|
def token
|
25
59
|
TokenClient.new(@configuration, self)
|
26
60
|
end
|
@@ -29,10 +63,26 @@ module KeycloakAdmin
|
|
29
63
|
ConfigurableTokenClient.new(@configuration, self)
|
30
64
|
end
|
31
65
|
|
66
|
+
def clients
|
67
|
+
ClientClient.new(@configuration, self)
|
68
|
+
end
|
69
|
+
|
70
|
+
def groups
|
71
|
+
GroupClient.new(@configuration, self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def roles
|
75
|
+
RoleClient.new(@configuration, self)
|
76
|
+
end
|
77
|
+
|
32
78
|
def users
|
33
79
|
UserClient.new(@configuration, self)
|
34
80
|
end
|
35
81
|
|
82
|
+
def user(user_id)
|
83
|
+
UserResource.new(@configuration, self, user_id)
|
84
|
+
end
|
85
|
+
|
36
86
|
def name_defined?
|
37
87
|
!@realm_name.nil?
|
38
88
|
end
|