keycloak-admin 1.0.24 → 1.1.0

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: f6bc5dc390440dedbf6a682c53717e334e4f174b31e43b7990dae87bed2e0bbf
4
- data.tar.gz: b37367aaa9726b48a266b55baf7fcebf772f302c18f215ad0e694d6e60421608
3
+ metadata.gz: 140b6a3bb680503f4bac8336250974b930535ef270f66b56b488ad78e182cd6b
4
+ data.tar.gz: 45c9d2ed7af63d6eaf027eebb4a6a9309d115d1fea88df9d8b4bb5c0d14ec7cc
5
5
  SHA512:
6
- metadata.gz: 869a2108bbffcdc242a438a20b6d8c06fa907354e2d0648cac91920d08ba070b2bf9cc35d710f1a1fcb40691176b84b515372af540bdc7383d4835217e9ce989
7
- data.tar.gz: ed68ed6de159d1d0bf87c298b49fab7fc94cc1d5f563ef25a2b56e922807ddb98b9fba69f189bc7ccc843380595afce42cc202e14b53f07fcc97f7c141145e43
6
+ metadata.gz: da197ebef3a7bc8fc82a95258eb684d007fbb69d48b62f6f19afd510fbbce11b30ac0c98f3b0731ebc56556311330707360a72f0505c9021d7f34d799a045534
7
+ data.tar.gz: e77461558697bbe7c372973673a3e58d9530720da6db2eaa76b79b1616e06ad05148cf843bd3c23a9d15a6fa55e27ac8988fccea776d593fd96e5f1130b6c0e1
data/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.1.0] - 2023-10-03
9
+
10
+ * Search for groups with parameters (thanks to @@tlloydthwaites)
11
+ * Get client by ID, Find client by Client ID, Update Client (thanks to @gee-forr)
12
+
8
13
  ## [1.0.24] - 2023-06-07
9
14
 
10
15
  * Revert the modifications on the feature 'Update a User' introduced in `1.0.22`. This implementation had breaking changes such as not being able to update several attributes (`first_name`, `email`, etc).
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keycloak-admin (1.0.24)
4
+ keycloak-admin (1.1.0)
5
5
  http-cookie (~> 1.0, >= 1.0.3)
6
6
  rest-client (~> 2.0)
7
7
 
@@ -15,9 +15,9 @@ GEM
15
15
  http-accept (1.7.0)
16
16
  http-cookie (1.0.5)
17
17
  domain_name (~> 0.5)
18
- mime-types (3.4.1)
18
+ mime-types (3.5.1)
19
19
  mime-types-data (~> 3.2015)
20
- mime-types-data (3.2023.0218.1)
20
+ mime-types-data (3.2023.0808)
21
21
  netrc (0.11.0)
22
22
  rest-client (2.1.0)
23
23
  http-accept (>= 1.7.0, < 2.0)
@@ -33,10 +33,10 @@ GEM
33
33
  rspec-expectations (3.12.3)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
35
  rspec-support (~> 3.12.0)
36
- rspec-mocks (3.12.5)
36
+ rspec-mocks (3.12.6)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
38
  rspec-support (~> 3.12.0)
39
- rspec-support (3.12.0)
39
+ rspec-support (3.12.1)
40
40
  unf (0.1.4)
41
41
  unf_ext
42
42
  unf_ext (0.0.8.2)
data/README.md CHANGED
@@ -21,7 +21,7 @@ To login on Keycloak's Admin API, you first need to setup a client.
21
21
 
22
22
  Go to your realm administration page and open `Clients`. Then, click on the `Create` button.
23
23
  On the first screen, enter:
24
- * `Client ID`: _e.g. my-app-admin-client_
24
+ * `Client ID`: _e.g. my-app-admin-client_
25
25
  * `Client Protocol`: select `openid-connect`
26
26
  * `Root URL`: let it blank
27
27
 
@@ -45,7 +45,7 @@ The next screen must be configured depending on how you want to authenticate:
45
45
  * In this gem's configuration (see Section `Configuration`):
46
46
  * Setup `username` and `password` according to your user's configuration
47
47
  * Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
48
- * If your client is `confidential`, copy its Client Secret to `client_secret`
48
+ * If your client is `confidential`, copy its Client Secret to `client_secret`
49
49
 
50
50
  ### Login with `Direct Access Grants` (Service account)
51
51
 
@@ -60,15 +60,15 @@ Using a service account to use the REST Admin API does not require to create a d
60
60
  * After saving this client
61
61
  * open the `Service Account Roles` and add relevant `realm-management.` client's roles. For instance: `view-users` if you want to search for users using this gem.
62
62
  * open the `Credentials` tab and copy the `Client Secret`
63
-
63
+
64
64
  * In this gem's configuration (see Section `Configuration`):
65
65
  * Set `use_service_account` to `true`
66
66
  * Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
67
- * Copy its Client Secret to `client_secret`
67
+ * Copy its Client Secret to `client_secret`
68
68
 
69
69
  ## Configuration
70
70
 
71
- To configure this gem, call `KeycloakAdmin.configure`.
71
+ To configure this gem, call `KeycloakAdmin.configure`.
72
72
  For instance, to configure this gem based on environment variables, write (and load if required) a `keycloak_admin.rb`:
73
73
  ```ruby
74
74
  KeycloakAdmin.configure do |config|
@@ -96,14 +96,14 @@ All options have a default value. However, all of them can be changed in your in
96
96
  | `client_realm_name` | `""`| String | Required | Name of the realm that contains the admin client. | `master` |
97
97
  | `client_id` | `admin-cli`| String | Required | Client that should be used to access admin capabilities. | `api-cli` |
98
98
  | `client_secret` | `nil`| String | Optional | If your client is `confidential`, this parameter must be specified. | `4e3c481c-f823-4a6a-b8a7-bf8c86e3eac3` |
99
- | `use_service_account` | `true` | Boolean | Required | `true` if the connection to the client uses a Service Account. `false` if the connection to the client uses a username/password credential. | `false` |
99
+ | `use_service_account` | `true` | Boolean | Required | `true` if the connection to the client uses a Service Account. `false` if the connection to the client uses a username/password credential. | `false` |
100
100
  | `username` | `nil`| String | Optional | Username to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `mummy` |
101
101
  | `password` | `nil`| String | Optional | Clear password to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `bobby` |
102
102
  | `logger` | `Logger.new(STDOUT)`| Logger | Optional | The logger used by `keycloak-admin` | `Rails.logger` | 
103
103
  | `rest_client_options` | `{}`| Hash | Optional | Options to pass to `RestClient` | `{ verify_ssl: OpenSSL::SSL::VERIFY_NONE }` | 
104
104
 
105
105
 
106
- ## Use Case
106
+ ## Use Cases
107
107
 
108
108
  ### Supported features
109
109
 
@@ -113,8 +113,8 @@ All options have a default value. However, all of them can be changed in your in
113
113
  * Reset credentials
114
114
  * Impersonate a user
115
115
  * Exchange a configurable token
116
- * Get list of clients
117
- * Create clients
116
+ * Get list of clients, or find a client by its id or client_id
117
+ * Create, update, and delete clients
118
118
  * Get list of groups, create/save a group
119
119
  * Get list of roles, save a role
120
120
  * Get list of realms, save/update/delete a realm
@@ -279,10 +279,26 @@ KeycloakAdmin.realm("a_realm").delete
279
279
 
280
280
  ### Get list of clients in a realm
281
281
 
282
- Returns an array of `KeycloakAdmin::ClientRepresentation`.
282
+ Returns an array of `KeycloakAdmin::ClientRepresentation` or a single `KeycloakAdmin::ClientRepresentation`
283
+
284
+ Finding a client by its `client_id` is a somewhat slow operation, as it requires fetching all clients and then filtering. Keycloak's API does not support fetching a client by its `client_id` directly.
283
285
 
284
286
  ```ruby
285
287
  KeycloakAdmin.realm("a_realm").clients.list
288
+ KeycloakAdmin.realm("a_realm").clients.get(id) # id is Keycloak's database id, not the client_id
289
+ KeycloakAdmin.realm("a_realm").clients.find_by_client_id(client_id)
290
+ ```
291
+
292
+ ### Updating a client
293
+
294
+ ```ruby
295
+ my_client = KeycloakAdmin.realm("a_realm").clients.get(id)
296
+
297
+ my_client.name = "My new client name"
298
+ my_client.description = "This is a new description"
299
+ my_client.redirect_uris << "https://www.example.com/auth/callback"
300
+
301
+ KeycloakAdmin.realm("a_realm").clients.update(client) # Returns the updated client
286
302
  ```
287
303
 
288
304
  ### Get list of groups in a realm
@@ -293,6 +309,22 @@ Returns an array of `KeycloakAdmin::GroupRepresentation`.
293
309
  KeycloakAdmin.realm("a_realm").groups.list
294
310
  ```
295
311
 
312
+ ### Search for a group
313
+
314
+ Returns an array of `KeycloakAdmin::GroupRepresentation`.
315
+
316
+ According to [the documentation](https://www.keycloak.org/docs-api/22.0.1/rest-api/index.html#_groups):
317
+ * When providing a `String` parameter, this produces an arbitrary search string
318
+ * When providing a `Hash`, you can specify other fields (_e.g_ q, max, first)
319
+
320
+ ```ruby
321
+ KeycloakAdmin.realm("a_realm").groups.search("MyGroup")
322
+ ```
323
+
324
+ ```ruby
325
+ KeycloakAdmin.realm("a_realm").groups.search({query: "MyGroup", exact: true, max: 1})
326
+ ```
327
+
296
328
  ### Save a group
297
329
 
298
330
  Returns the id of saved `group` provided, which must be of type `KeycloakAdmin::GroupRepresentation`.
@@ -415,4 +447,3 @@ From the `keycloak-admin-api` directory:
415
447
  $ docker build . -t keycloak-admin:test
416
448
  $ docker run -v `pwd`:/usr/src/app/ keycloak-admin:test rspec spec
417
449
  ```
418
-
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "keycloak-admin"
6
+ require "byebug"
7
+
8
+ require "irb"
9
+ IRB.start
@@ -6,6 +6,13 @@ module KeycloakAdmin
6
6
  @realm_client = realm_client
7
7
  end
8
8
 
9
+ def get(id)
10
+ response = execute_http do
11
+ RestClient::Resource.new(clients_url(id), @configuration.rest_client_options).get(headers)
12
+ end
13
+ ClientRepresentation.from_hash(JSON.parse(response))
14
+ end
15
+
9
16
  def save(client_representation)
10
17
  execute_http do
11
18
  RestClient::Resource.new(clients_url, @configuration.rest_client_options).post(
@@ -21,6 +28,10 @@ module KeycloakAdmin
21
28
  JSON.parse(response).map { |client_as_hash| ClientRepresentation.from_hash(client_as_hash) }
22
29
  end
23
30
 
31
+ def find_by_client_id(client_id)
32
+ list.find { |client| client.client_id == client_id }
33
+ end
34
+
24
35
  def delete(id)
25
36
  execute_http do
26
37
  RestClient::Resource.new(clients_url(id), @configuration.rest_client_options).delete(headers)
@@ -28,6 +39,16 @@ module KeycloakAdmin
28
39
  true
29
40
  end
30
41
 
42
+ def update(client_representation)
43
+ execute_http do
44
+ RestClient::Resource.new(clients_url(client_representation.id), @configuration.rest_client_options).put(
45
+ create_payload(client_representation), headers
46
+ )
47
+ end
48
+
49
+ get(client_representation.id)
50
+ end
51
+
31
52
  def get_service_account_user(client_id)
32
53
  response = execute_http do
33
54
  RestClient::Resource.new(service_account_user_url(client_id), @configuration.rest_client_options).get(headers)
@@ -7,8 +7,20 @@ module KeycloakAdmin
7
7
  end
8
8
 
9
9
  def list
10
+ search(nil)
11
+ end
12
+
13
+ def search(query)
14
+ derived_headers = case query
15
+ when String
16
+ headers.merge({params: { search: query }})
17
+ when Hash
18
+ headers.merge({params: query })
19
+ else
20
+ headers
21
+ end
10
22
  response = execute_http do
11
- RestClient::Resource.new(groups_url, @configuration.rest_client_options).get(headers)
23
+ RestClient::Resource.new(groups_url, @configuration.rest_client_options).get(derived_headers)
12
24
  end
13
25
  JSON.parse(response).map { |group_as_hash| GroupRepresentation.from_hash(group_as_hash) }
14
26
  end
@@ -1,3 +1,3 @@
1
1
  module KeycloakAdmin
2
- VERSION = "1.0.24"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -22,6 +22,49 @@ RSpec.describe KeycloakAdmin::ClientClient do
22
22
  end
23
23
  end
24
24
 
25
+ describe "#get" do
26
+ let(:realm_name) { "valid-realm" }
27
+ let(:id) { "test_client_id" }
28
+ let(:client_name) { "test_client_name" }
29
+
30
+ before(:each) do
31
+ @client_client = KeycloakAdmin.realm(realm_name).clients
32
+
33
+ stub_token_client
34
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '{"id":"test_client_id","name":"test_client_name"}'
35
+ end
36
+
37
+ it "finds a client" do
38
+ client = @client_client.get(id)
39
+ expect(client.name).to eq client_name
40
+ expect(client.id).to eq id
41
+ end
42
+ end
43
+
44
+ describe "#find_by_client_id" do
45
+ let(:realm_name) { "valid-realm" }
46
+ let(:client_id) { "my_client_id" }
47
+ let(:client_name) { "test_client_name" }
48
+
49
+ before(:each) do
50
+ @client_client = KeycloakAdmin.realm(realm_name).clients
51
+
52
+ stub_token_client
53
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '[{"id":"test_client_id","clientId": "my_client_id","name":"test_client_name"},{"id":"test_client_id_2","clientId":"client_id_2","name":"test_client_name_2"}]'
54
+ end
55
+
56
+ it "finds a client it has" do
57
+ client = @client_client.find_by_client_id(client_id)
58
+ expect(client.name).to eq client_name
59
+ expect(client.client_id).to eq client_id
60
+ end
61
+
62
+ it "returns nil if it doesn't have the client" do
63
+ client = @client_client.find_by_client_id("client_id_3")
64
+ expect(client).to be_nil
65
+ end
66
+ end
67
+
25
68
  describe "#list" do
26
69
  let(:realm_name) { "valid-realm" }
27
70
 
@@ -51,6 +94,25 @@ RSpec.describe KeycloakAdmin::ClientClient do
51
94
  end
52
95
  end
53
96
 
97
+ describe "#update" do
98
+ let(:realm_name) { "valid-realm" }
99
+ let(:client) { KeycloakAdmin::ClientRepresentation.from_hash({ "id" => "test_client_id", "clientId" => "my-client", "name" => "old_name" }) }
100
+
101
+ before(:each) do
102
+ @client_client = KeycloakAdmin.realm(realm_name).clients
103
+
104
+ stub_token_client
105
+ allow_any_instance_of(RestClient::Resource).to receive(:put).and_return ''
106
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '{"id":"test_client_id", "clientId": "my-client","name":"new_name"}'
107
+ end
108
+
109
+ it "updates a client" do
110
+ updated_client = @client_client.update(client)
111
+
112
+ expect(updated_client.name).to eq "new_name"
113
+ end
114
+ end
115
+
54
116
  describe "#delete" do
55
117
  let(:realm_name) { "valid-realm" }
56
118
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keycloak-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.24
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorent Lempereur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-07 00:00:00.000000000 Z
11
+ date: 2023-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-cookie
@@ -87,6 +87,7 @@ files:
87
87
  - Gemfile.lock
88
88
  - MIT-LICENSE
89
89
  - README.md
90
+ - bin/console
90
91
  - keycloak-admin.gemspec
91
92
  - lib/keycloak-admin.rb
92
93
  - lib/keycloak-admin/client/attack_detection_client.rb