rails_keycloak_authorization 0.0.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +139 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/rails_keycloak_authorization_manifest.js +1 -0
  6. data/app/assets/stylesheets/rails_keycloak_authorization/application.css +15 -0
  7. data/app/controllers/concerns/rails_keycloak_authorization/with_htmx_layout.rb +15 -0
  8. data/app/controllers/concerns/rails_keycloak_authorization/with_keycloak_admin.rb +35 -0
  9. data/app/controllers/concerns/rails_keycloak_authorization/with_routes_reader.rb +26 -0
  10. data/app/controllers/rails_keycloak_authorization/application_controller.rb +4 -0
  11. data/app/controllers/rails_keycloak_authorization/management_controller.rb +9 -0
  12. data/app/controllers/rails_keycloak_authorization/permissions_controller.rb +39 -0
  13. data/app/controllers/rails_keycloak_authorization/policies_controller.rb +19 -0
  14. data/app/controllers/rails_keycloak_authorization/resources_controller.rb +31 -0
  15. data/app/controllers/rails_keycloak_authorization/routes_controller.rb +23 -0
  16. data/app/controllers/rails_keycloak_authorization/scopes_controller.rb +48 -0
  17. data/app/helpers/rails_keycloak_authorization/application_helper.rb +4 -0
  18. data/app/helpers/rails_keycloak_authorization/resources_helper.rb +5 -0
  19. data/app/jobs/rails_keycloak_authorization/application_job.rb +4 -0
  20. data/app/mailers/rails_keycloak_authorization/application_mailer.rb +6 -0
  21. data/app/models/rails_keycloak_authorization/application_record.rb +5 -0
  22. data/app/services/rails_keycloak_authorization/keycloak_admin_ruby_agent.rb +145 -0
  23. data/app/views/layouts/rails_keycloak_authorization/application.html.erb +14 -0
  24. data/app/views/layouts/rails_keycloak_authorization/htmx.html.erb +14 -0
  25. data/app/views/rails_keycloak_authorization/management/index.html.erb +79 -0
  26. data/app/views/rails_keycloak_authorization/permissions/index.html.erb +41 -0
  27. data/app/views/rails_keycloak_authorization/permissions/resource_scopes_select.html.erb +7 -0
  28. data/app/views/rails_keycloak_authorization/policies/index.html.erb +23 -0
  29. data/app/views/rails_keycloak_authorization/resources/index.html.erb +5 -0
  30. data/app/views/rails_keycloak_authorization/resources/new.html.erb +4 -0
  31. data/app/views/rails_keycloak_authorization/resources/show.html.erb +28 -0
  32. data/app/views/rails_keycloak_authorization/routes/index.html.erb +58 -0
  33. data/app/views/rails_keycloak_authorization/routes/show.html.erb +6 -0
  34. data/app/views/rails_keycloak_authorization/scopes/index.html.erb +9 -0
  35. data/app/views/rails_keycloak_authorization/scopes/show.html.erb +33 -0
  36. data/config/routes.rb +13 -0
  37. data/lib/rails_keycloak_authorization/engine.rb +8 -0
  38. data/lib/rails_keycloak_authorization/version.rb +3 -0
  39. data/lib/rails_keycloak_authorization.rb +77 -0
  40. data/lib/tasks/rails_keycloak_authorization_tasks.rake +170 -0
  41. metadata +128 -0
@@ -0,0 +1,79 @@
1
+ <h1 class="text-lg font-medium text-center text-gray-500">Rails Keycloak Authorization Gem</h1>
2
+
3
+ <div class="text-sm font-medium text-center text-gray-500 border-b border-gray-200 dark:text-gray-400 dark:border-gray-700" role="tablist">
4
+ <ul class="flex flex-wrap -mb-px">
5
+ <li>
6
+ <button
7
+ id="routes-tab"
8
+ hx-get="<%= routes_path %>"
9
+ class="inline-block p-4 rounded-t-lg border-b-2 text-blue-600 border-blue-600 dark:text-blue-500 dark:border-blue-500"
10
+ hx-on::after-request="
11
+ document.querySelector('#routes-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-blue-600 border-blue-600 dark:text-blue-500 dark:border-blue-500';
12
+ document.querySelector('#policies-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
13
+ document.querySelector('#permissions-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
14
+ document.querySelector('#resources-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
15
+ "
16
+ hx-target="#tab-content"
17
+ hx-swap="innerHTML"
18
+ role="tab"
19
+ aria-selected="true"
20
+ aria-controls="tab-content">Rails Routes</button>
21
+ </li>
22
+
23
+ <li>
24
+ <button
25
+ id="policies-tab"
26
+ hx-get="<%= policies_path %>"
27
+ class="inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500"
28
+ hx-on::after-request="
29
+ document.querySelector('#permissions-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
30
+ document.querySelector('#routes-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
31
+ document.querySelector('#policies-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-blue-600 border-blue-600 dark:text-blue-500 dark:border-blue-500';
32
+ document.querySelector('#resources-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
33
+ "
34
+ hx-target="#tab-content"
35
+ hx-swap="innerHTML"
36
+ role="tab"
37
+ aria-selected="true"
38
+ aria-controls="tab-content">Keycloak Policies</button>
39
+ </li>
40
+
41
+ <li>
42
+ <button
43
+ id="permissions-tab"
44
+ hx-get="<%= permissions_path %>"
45
+ class="inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500"
46
+ hx-on::after-request="
47
+ document.querySelector('#routes-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
48
+ document.querySelector('#policies-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
49
+ document.querySelector('#permissions-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-blue-600 border-blue-600 dark:text-blue-500 dark:border-blue-500';
50
+ document.querySelector('#resources-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
51
+ "
52
+ hx-target="#tab-content"
53
+ hx-swap="innerHTML"
54
+ role="tab"
55
+ aria-selected="true"
56
+ aria-controls="tab-content">Keycloak Permissions</button>
57
+ </li>
58
+
59
+ <li>
60
+ <button
61
+ id="resources-tab"
62
+ hx-get="<%= resources_path %>"
63
+ class="inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500"
64
+ hx-on::after-request="
65
+ document.querySelector('#routes-tab').className ='inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
66
+ document.querySelector('#policies-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
67
+ document.querySelector('#permissions-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-gray-600 border-gray-600 dark:text-gray-500 dark:border-gray-500';
68
+ document.querySelector('#resources-tab').className = 'inline-block p-4 rounded-t-lg border-b-2 text-blue-600 border-blue-600 dark:text-blue-500 dark:border-blue-500';
69
+ "
70
+ hx-target="#tab-content"
71
+ hx-swap="innerHTML"
72
+ role="tab"
73
+ aria-selected="false"
74
+ aria-controls="tab-content">Keycloak Resource</button>
75
+ </li>
76
+ </ul>
77
+ </div>
78
+
79
+ <div id="tab-content" role="tabpanel" class="tab-content" hx-get="<%= routes_path %>" hx-trigger="load delay:100ms" hx-swap="innerHTML"></div>
@@ -0,0 +1,41 @@
1
+ <% if @permissions.empty? %>
2
+ <div>No permissions created yet!</div>
3
+ <% end %>
4
+
5
+ <% @permissions.each do |permission| %>
6
+ <div>name:</div>
7
+ <div><%= permission.name %></div>
8
+ <div>type:</div>
9
+ <div><%= permission.type %></div>
10
+ <% end %>
11
+
12
+
13
+ <form hx-post="<%= permissions_path %>">
14
+ <div>
15
+ <label for="keycloak_policy_id">Policy</label>
16
+ <select name="keycloak_policy_id" hx-indicator=".htmx-indicator">
17
+ <option value="" selected disabled>Select Policy</option>
18
+ <% @policies.map do |policy| %>
19
+ <option value="<%= policy.id %>"><%= policy.name %></option>
20
+ <% end %>
21
+ </select>
22
+ </div>
23
+
24
+ <div>
25
+ <label for="keycloak_resource_id">Resource</label>
26
+ <select name="keycloak_resource_id"
27
+ hx-get="<%= resource_scopes_select_permissions_path %>"
28
+ hx-target="#scopes"
29
+ hx-indicator=".htmx-indicator">
30
+ <option value="" selected disabled>Select Resource</option>
31
+ <% @resources.map do |resource| %>
32
+ <option value="<%= resource.id %>"><%= resource.name %></option>
33
+ <% end %>
34
+ </select>
35
+ </div>
36
+
37
+ <div id="scopes"></div>
38
+ <button
39
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
40
+ type="submit">Create</button>
41
+ </form>
@@ -0,0 +1,7 @@
1
+ <label for="keycloak_scope_id">Scope</label>
2
+ <select name="keycloak_scope_id" hx-indicator=".htmx-indicator">
3
+ <option value="" selected disabled>Select Scope</option>
4
+ <% @resource_scopes.map do |scope| %>
5
+ <option value="<%= scope.id %>"><%= scope.name %></option>
6
+ <% end %>
7
+ </select>
@@ -0,0 +1,23 @@
1
+ <h1 class="text-center text-gray-500">Policies</h1>
2
+ <% if @policies.empty? %>
3
+ <p class="inline">Default Policy for </p>
4
+ <form class="inline" hx-post="<%= policies_path %>">
5
+ <input id="keycloak_policy_name" name="keycloak_policy_name" value="<%= @default_policy_name %>" type="text">
6
+ <label for="keycloak_realm_role">Role</label>
7
+ <select name="keycloak_realm_role_id" hx-indicator=".htmx-indicator">
8
+ <% @realm_roles.map do |role| %>
9
+ <option value="<%= role.id %>" <%= role.name.include?("default") ? "selected=selected" : "" %>>
10
+ <%= role.name %>
11
+ </option>
12
+ <% end %>
13
+ </select>
14
+ <button
15
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
16
+ type="submit">Create</button>
17
+ </form>
18
+ <% else %>
19
+ <div class="text-gray-500">Current Policy</div>
20
+ <% @policies.map do |policy| %>
21
+ <p><%= policy.name %></p>
22
+ <% end %>
23
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <h1>Resources</h1>
2
+ <% @controller_names.each do |controller_name| %>
3
+ Rails controller: <%= controller_name %>
4
+ keycloak resource: <%= controller_name %>
5
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <form hx-post="<%= resources_path %>">
2
+ <input type="text" name="route_id" hidden="hidden" value="<%= @route.defaults[:controller] %>">
3
+ <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded" type="Submit">Create Resource?</button>
4
+ </form>
@@ -0,0 +1,28 @@
1
+ <% if @keycloak_resource %>
2
+ <table class="table-auto">
3
+ <thead>
4
+ <tr><th>Controller</th></tr>
5
+ </thead>
6
+ <tbody>
7
+ <tr><td><%= @keycloak_resource.name %></td></tr>
8
+ </tbody>
9
+ </table>
10
+
11
+ <table class="table-auto">
12
+ <thead>
13
+ <tr>
14
+ <th>Scope</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <tr>
19
+ <td>
20
+ <div hx-get="<%= scope_path("scope:#{@route.defaults[:action]}", keycloak_resource_id: @keycloak_resource.id, keycloak_scope_name: @route.defaults[:action]) %>" hx-trigger="load" ></div>
21
+ </td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+
26
+ <% else %>
27
+ <div hx-get="<%= new_resource_path(route_id: @route.name) %>" hx-trigger="load" ></div>
28
+ <% end %>
@@ -0,0 +1,58 @@
1
+ <table>
2
+ <caption>Available Routes</caption>
3
+ <thead>
4
+ <tr>
5
+ <th scope="col" class="text-left">Verb</th>
6
+ <th scope="col" class="text-left">Name</th>
7
+ <th scope="col" class="text-left">Path</th>
8
+ <th scope="col" class="text-left">Controller</th>
9
+ <th scope="col" class="text-left">Action</th>
10
+ <th scope="col" class="text-left">Inspect</th>
11
+ </tr>
12
+ </thead>
13
+ <% @routes.each do |route| %>
14
+ <tbody>
15
+ <tr class="p-2 bg-gray-100 border border-gray-200">
16
+ <td class="text-left">
17
+ <%= route.verb %>
18
+ </td>
19
+ <td class="text-left">
20
+ <%= route.name %>
21
+ </td>
22
+ <td class="text-left">
23
+ <%= route.path.spec.to_s %>
24
+ </td>
25
+ <td class="text-left">
26
+ <%= route.defaults[:controller] %>
27
+ </td>
28
+ <td class="text-left">
29
+ <%= route.defaults[:action] %>
30
+ </td>
31
+ <td class="text-left">
32
+ <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
33
+ popovertarget="modal"
34
+ hx-get="<%= route_path(route.name) %>"
35
+ hx-trigger="click"
36
+ hx-target="#modal-content"
37
+ hx-swap="innserHtml">Inspect</button>
38
+ </td>
39
+ </tr>
40
+ <tbody>
41
+ <% end %>
42
+ </table>
43
+
44
+ <div popover id="modal" class="border border-gray-200">
45
+ <style>
46
+ :popover-open {
47
+ width: 600px;
48
+ height: 400px;
49
+ }
50
+ </style>
51
+ <div class="bg-gray-200 h-5/6 w-full p-4" id="modal-content" >
52
+ <h1>Modal Dialog</h1>
53
+ This is the modal content. You can put anything here, like text, or a form, or an image.
54
+ </div>
55
+ <div class="text-center pt-2">
56
+ <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded" hx-on:click="document.getElementById('modal').hidePopover()">Close</button>
57
+ </div>
58
+ </div>
@@ -0,0 +1,6 @@
1
+ <h1 class="text-xl">Keycloak Authorization Status</h1>
2
+
3
+ <div>Route: <%= @route.name %></div>
4
+
5
+ <div hx-get="<%= resource_path(@route.name) %>" hx-trigger="load" ></div>
6
+
@@ -0,0 +1,9 @@
1
+ <% @scopes.each do |scope| %>
2
+ <table>
3
+ <tbody>
4
+ <tr>
5
+ <td><%= scope.name %></td>
6
+ </tr>
7
+ </tbody>
8
+ </table>
9
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <div id="scope">
2
+ <% if @resource_scope %>
3
+ <div>Resource Attached Scope: <b><%= @resource_scope.name %></b></div>
4
+ <div>Check <b>Keycloak Policies</b> tab</div>
5
+
6
+ <% elsif @available_scope %>
7
+ Available Scope to attach: <%= @available_scope.name %>
8
+
9
+ <button
10
+ class="block bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
11
+ hx-post="<%= attach_scope_path(@keycloak_scope_name) %>"
12
+ hx-target="#scope"
13
+ hx-vals='{
14
+ "keycloak_scope_name": "<%= @keycloak_scope_name %>",
15
+ "keycloak_resource_id": "<%= @keycloak_resource_id %>"
16
+ }'
17
+ >
18
+ Attach scope <%= @keycloak_scope_name %> to resource ?
19
+ </button>
20
+
21
+ <% else %>
22
+ Scope <b><%= @keycloak_scope_name %></b> not created yet.
23
+ <button
24
+ class="block bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
25
+ hx-post="<%= scopes_path %>"
26
+ hx-target="#scope"
27
+ hx-vals='{
28
+ "keycloak_scope_name": "<%= @keycloak_scope_name %>",
29
+ "keycloak_resource_id": "<%= @keycloak_resource_id %>"
30
+ }'
31
+ >Create Scope?</button>
32
+ <% end %>
33
+ </div>
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ RailsKeycloakAuthorization::Engine.routes.draw do
2
+ root "management#index"
3
+ resources :management, only: [:index]
4
+ resources :routes, only: [:index, :show]
5
+ resources :policies, only: [:index, :create]
6
+ resources :permissions, only: [:index, :create] do
7
+ get :resource_scopes_select, on: :collection
8
+ end
9
+ resources :resources, only: [:create, :show, :new, :index]
10
+ resources :scopes, only: [:index, :show, :new, :create] do
11
+ post :attach, on: :member
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module RailsKeycloakAuthorization
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsKeycloakAuthorization
4
+ initializer "rails_keycloak_authorization.middleware" do |app|
5
+ app.middleware.use RailsKeycloakAuthorization::Middleware
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module RailsKeycloakAuthorization
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,77 @@
1
+ require "rails_keycloak_authorization/version"
2
+ require "rails_keycloak_authorization/engine"
3
+
4
+ module RailsKeycloakAuthorization
5
+ mattr_accessor :keycloak_realm
6
+ mattr_accessor :keycloak_server_url
7
+ mattr_accessor :keycloak_admin_username
8
+ mattr_accessor :keycloak_admin_password
9
+ mattr_accessor :match_patterns
10
+ mattr_accessor :client_id
11
+
12
+ class Middleware
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ if should_process?(env["REQUEST_URI"],)
19
+ if !env["HTTP_AUTHORIZATION"]
20
+ [403, {}, ["Authentication Failed"]]
21
+ elsif authorize!(env['REQUEST_URI'], env['HTTP_AUTHORIZATION'])
22
+ @app.call(env)
23
+ else
24
+ [403, {}, ["Authorization Failed"]]
25
+ end
26
+ else
27
+ @app.call(env)
28
+ end
29
+ end
30
+
31
+ def should_process?(request_uri)
32
+ RailsKeycloakAuthorization.match_patterns.detect do |r|
33
+ r.match(request_uri)
34
+ end
35
+ end
36
+
37
+ def authorize!(request_uri, http_authorization)
38
+ route = Rails.application.routes.recognize_path(request_uri)
39
+ uri = uri(RailsKeycloakAuthorization.keycloak_server_url, RailsKeycloakAuthorization.keycloak_realm)
40
+ request = http_request(uri, http_authorization, route)
41
+ response = http_client(uri).request(request)
42
+ response.is_a?(Net::HTTPSuccess)
43
+ end
44
+
45
+ def http_request(uri, http_authorization, route)
46
+ request = Net::HTTP::Post.new(uri, {
47
+ 'Content-Type' => 'application/x-www-form-urlencoded',
48
+ 'Authorization' => http_authorization,
49
+ })
50
+ permission = "#{route[:controller]}_controller##{route[:action]}"
51
+ request.body = URI.encode_www_form({
52
+ audience: "#{RailsKeycloakAuthorization.client_id}",
53
+ grant_type: grant_type,
54
+ permission: permission,
55
+ response_mode: "permissions",
56
+ permission_resource_format: "id",
57
+ permission_resource_matching_uri: false
58
+ })
59
+ request
60
+ end
61
+
62
+ def grant_type
63
+ "urn:ietf:params:oauth:grant-type:uma-ticket"
64
+ end
65
+
66
+ def uri(keycloak_server_url, keycloak_realm)
67
+ URI("#{keycloak_server_url}/realms/#{keycloak_realm}/protocol/openid-connect/token")
68
+ end
69
+
70
+ def http_client(uri)
71
+ http = Net::HTTP.new(uri.host, uri.port)
72
+ http.use_ssl = Rails.env.production?
73
+ http.read_timeout = ENV.fetch("KEYCLOAK_AUTHORIZATION_TIMEOUT", 1).to_i
74
+ http
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,170 @@
1
+ require 'keycloak-admin'
2
+
3
+ namespace :'rails-keycloak-authorization' do
4
+ desc "Explaining what the task does"
5
+ task :create_default_scopes do
6
+ keycloak_admin_configure
7
+ realm_name = ENV["KEYCLOAK_AUTH_CLIENT_REALM_NAME"]
8
+ client = KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV["KEYCLOAK_AUTH_CLIENT_ID"])
9
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("POST", "POST Scope", "")
10
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("GET", "GET Scope", "")
11
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("PUT", "PUT Scope", "")
12
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("PATCH", "PATCH Scope", "")
13
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("DELETE", "DESTROY Scope", "")
14
+ end
15
+
16
+ desc "Explaining what the task does"
17
+ task :create_resources do
18
+ create_resource "Organization"
19
+ end
20
+
21
+ desc "Explaining what the task does"
22
+ task :create_policy do
23
+ create_policy
24
+ end
25
+
26
+ desc "Explaining what the task does"
27
+ task :create_permission do
28
+ create_permission
29
+ end
30
+
31
+
32
+ desc "Explaining what the task does"
33
+ task :validate_keycloak_admin_ruby_permissions do
34
+ puts "Validating, Rails::Keycloak::Authorization ...."
35
+ keycloak_admin_configure
36
+ realm_name = ENV["KEYCLOAK_AUTH_CLIENT_REALM_NAME"]
37
+
38
+ client = KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV["KEYCLOAK_AUTH_CLIENT_ID"])
39
+ client.authorization_services_enabled = true
40
+ KeycloakAdmin.realm(realm_name).clients.update(client)
41
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).list.each{|scope| puts scope.name }
42
+ KeycloakAdmin.realm(realm_name).authz_resources(client.id).list.each{|scope| puts scope.uris }
43
+ KeycloakAdmin.realm(realm_name).authz_policies(client.id, 'role').list.each{|scope| puts "Policy #{scope.name}" }
44
+
45
+ realm_role = KeycloakAdmin.realm(realm_name).roles.get("default-roles-dummy")
46
+
47
+ scope_1 = KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("POST_1", "POST 1 scope", "http://asdas")
48
+ scope_2 = KeycloakAdmin.realm(realm_name).authz_scopes(client.id).create!("POST_2", "POST 2 scope", "http://asdas")
49
+ puts KeycloakAdmin.realm(realm_name).authz_scopes(client.id).search("POST")
50
+ puts KeycloakAdmin.realm(realm_name).authz_scopes(client.id).get(scope_1.id)
51
+
52
+ # resource = KeycloakAdmin.realm(realm_name).authz_resources(client.id).create!(
53
+ # "Dummy Resource",
54
+ # "type",
55
+ # ["/asdf/*", "/tmp/"],
56
+ # true,
57
+ # "display_name",
58
+ # [{id: scope_1.id, name: scope_1.name},{id: scope_2.id, name: scope_2.name}],
59
+ # {"a": ["b", "c"]}
60
+ # )
61
+ resource = KeycloakAdmin.realm(realm_name).authz_resources(client.id).create!("Dummy Resource", "type", ["/asdf/*", "/tmp/"], true, "display_name", [], {"a": ["b", "c"]})
62
+
63
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).find_by("Dummy Resource", "", "", "", "").first.name
64
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).find_by("", "type", "", "", "").first.name
65
+
66
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).get(resource.id).scopes.count
67
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).get(resource.id).uris.count
68
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).update(resource.id,
69
+ {
70
+ "name": "Dummy Resource",
71
+ "type": "type",
72
+ "owner_managed_access": true,
73
+ "display_name": "display_name",
74
+ "attributes": {"a":["b","c"]},
75
+ "uris": [ "/asdf/*" , "/tmp/45" ],
76
+ "scopes":[
77
+ {name: scope_1.name},{name: scope_2.name}
78
+ ],
79
+ "icon_uri": "https://icon.ico"
80
+ }
81
+ )
82
+
83
+ puts KeycloakAdmin.realm(realm_name).authz_resources(client.id).update(resource.id,
84
+ {
85
+ "name": "Dummy Resource",
86
+ "scopes":[
87
+ {name: scope_1.name}
88
+ ]
89
+ }
90
+ )
91
+
92
+ policy = KeycloakAdmin.realm(realm_name).authz_policies(client.id, 'role').create!("Policy 1", "description", "role", "POSITIVE", "UNANIMOUS", true, [{id: realm_role.id, required: true}])
93
+ puts KeycloakAdmin.realm(realm_name).authz_policies(client.id, 'role').find_by("Policy 1", "role").first.name
94
+ puts KeycloakAdmin.realm(realm_name).authz_policies(client.id, 'role').get(policy.id).name
95
+ scope_permission = KeycloakAdmin.realm(realm_name).authz_permissions(client.id, :scope).create!("Dummy Scope Permission", "scope description", "UNANIMOUS", "POSITIVE", [resource.id], [policy.id], [scope_1.id, scope_2.id], "")
96
+ resource_permission = KeycloakAdmin.realm(realm_name).authz_permissions(client.id, :resource).create!("Dummy Resource Permission", "resource description", "UNANIMOUS", "POSITIVE", [resource.id], [policy.id], nil, "")
97
+ resource_permissions = KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "", resource.id).list
98
+ puts resource_permissions.length
99
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "resource").get(resource_permission.id)
100
+ debugger
101
+ resource_scopes = KeycloakAdmin.realm(realm_name).authz_scopes(client.id, resource.id).list
102
+ puts resource_scopes.length
103
+ KeycloakAdmin.realm(realm_name).authz_permissions(client.id, 'scope').list.map{|r| puts r.name}
104
+ KeycloakAdmin.realm(realm_name).authz_permissions(client.id, 'resource').list.map{|r| puts r.name}
105
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "resource").find_by(resource_permission.name, nil).first.name
106
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "resource").find_by(resource_permission.name, resource.id).first.name
107
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "scope").find_by(scope_permission.name, resource.id).first.name
108
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "scope").find_by(scope_permission.name, resource.id, "POST_1").first.name
109
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "resource").find_by(nil, resource.id).first.name
110
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "scope").find_by(nil, resource.id).first.name
111
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "scope").find_by(nil, resource.id, "POST_1").first.name
112
+ puts KeycloakAdmin.realm(realm_name).authz_permissions(client.id, "scope").find_by(scope_permission.name, nil).first.name
113
+ # KeycloakAdmin.realm(realm_name).authz_permissions(client.id).find_by(resource_permission.name, resource.id, "scope", nil )
114
+
115
+ KeycloakAdmin.realm(realm_name).authz_permissions(client.id, 'scope').delete(scope_permission.id)
116
+ KeycloakAdmin.realm(realm_name).authz_permissions(client.id, 'resource').delete(resource_permission.id)
117
+ KeycloakAdmin.realm(realm_name).authz_policies(client.id, 'role').delete(policy.id)
118
+ KeycloakAdmin.realm(realm_name).authz_resources(client.id).delete(resource.id)
119
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).delete(scope_1.id)
120
+ KeycloakAdmin.realm(realm_name).authz_scopes(client.id).delete(scope_2.id)
121
+ puts "Validation, Rails::Keycloak::Authorization done."
122
+ end
123
+
124
+
125
+
126
+
127
+
128
+ def create_resource(model_name)
129
+ keycloak_admin_configure
130
+ resource_name = model_name.downcase.pluralize
131
+ client = KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV.fetch("KEYCLOAK_AUTH_CLIENT_ID"))
132
+ scopes = KeycloakAdmin.realm(realm_name).authz_scopes(client.id).list.reverse
133
+ KeycloakAdmin.realm(realm_name)
134
+ .authz_resources(client.id)
135
+ .create!(model_name,
136
+ "type",
137
+ ["/#{resource_name}/*", "/#{resource_name}"],
138
+ true,
139
+ "#{resource_name.capitalize} Resource",
140
+ scopes.map{|scope| {id: scope.id, name: scope.name} },
141
+ { "model": resource_name }
142
+ )
143
+ end
144
+
145
+ def create_policy
146
+ keycloak_admin_configure
147
+ realm_role = KeycloakAdmin.realm(realm_name).roles.get("default-roles-dummy")
148
+ client = KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV["KEYCLOAK_AUTH_CLIENT_ID"])
149
+ KeycloakAdmin
150
+ .realm(realm_name)
151
+ .authz_policies(client.id, 'role')
152
+ .create!("Policy 1",
153
+ "description",
154
+ "role",
155
+ "POSITIVE",
156
+ "UNANIMOUS",
157
+ true,
158
+ [{id: realm_role.id, required: true}]
159
+ )
160
+ end
161
+ def create_permission
162
+ keycloak_admin_configure
163
+ client = KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV["KEYCLOAK_AUTH_CLIENT_ID"])
164
+ resource = KeycloakAdmin.realm(realm_name).authz_resources(client.id).find_by(client.id, "Organization", "", "", "").first
165
+ policy = KeycloakAdmin.realm(realm_name).authz_policies( client.id, 'role').find_by("Policy 1", "role").first
166
+ scope_permission = KeycloakAdmin.realm(realm_name).authz_permissions(client.id, :scope).create!("Organizations Scope Permission", "scope description", "UNANIMOUS", "POSITIVE", [resource.id], [policy.id], ["POST", "GET", "PATCH", "PUT", "DELETE"], "")
167
+ end
168
+
169
+
170
+ end