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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +139 -0
- data/Rakefile +8 -0
- data/app/assets/config/rails_keycloak_authorization_manifest.js +1 -0
- data/app/assets/stylesheets/rails_keycloak_authorization/application.css +15 -0
- data/app/controllers/concerns/rails_keycloak_authorization/with_htmx_layout.rb +15 -0
- data/app/controllers/concerns/rails_keycloak_authorization/with_keycloak_admin.rb +35 -0
- data/app/controllers/concerns/rails_keycloak_authorization/with_routes_reader.rb +26 -0
- data/app/controllers/rails_keycloak_authorization/application_controller.rb +4 -0
- data/app/controllers/rails_keycloak_authorization/management_controller.rb +9 -0
- data/app/controllers/rails_keycloak_authorization/permissions_controller.rb +39 -0
- data/app/controllers/rails_keycloak_authorization/policies_controller.rb +19 -0
- data/app/controllers/rails_keycloak_authorization/resources_controller.rb +31 -0
- data/app/controllers/rails_keycloak_authorization/routes_controller.rb +23 -0
- data/app/controllers/rails_keycloak_authorization/scopes_controller.rb +48 -0
- data/app/helpers/rails_keycloak_authorization/application_helper.rb +4 -0
- data/app/helpers/rails_keycloak_authorization/resources_helper.rb +5 -0
- data/app/jobs/rails_keycloak_authorization/application_job.rb +4 -0
- data/app/mailers/rails_keycloak_authorization/application_mailer.rb +6 -0
- data/app/models/rails_keycloak_authorization/application_record.rb +5 -0
- data/app/services/rails_keycloak_authorization/keycloak_admin_ruby_agent.rb +145 -0
- data/app/views/layouts/rails_keycloak_authorization/application.html.erb +14 -0
- data/app/views/layouts/rails_keycloak_authorization/htmx.html.erb +14 -0
- data/app/views/rails_keycloak_authorization/management/index.html.erb +79 -0
- data/app/views/rails_keycloak_authorization/permissions/index.html.erb +41 -0
- data/app/views/rails_keycloak_authorization/permissions/resource_scopes_select.html.erb +7 -0
- data/app/views/rails_keycloak_authorization/policies/index.html.erb +23 -0
- data/app/views/rails_keycloak_authorization/resources/index.html.erb +5 -0
- data/app/views/rails_keycloak_authorization/resources/new.html.erb +4 -0
- data/app/views/rails_keycloak_authorization/resources/show.html.erb +28 -0
- data/app/views/rails_keycloak_authorization/routes/index.html.erb +58 -0
- data/app/views/rails_keycloak_authorization/routes/show.html.erb +6 -0
- data/app/views/rails_keycloak_authorization/scopes/index.html.erb +9 -0
- data/app/views/rails_keycloak_authorization/scopes/show.html.erb +33 -0
- data/config/routes.rb +13 -0
- data/lib/rails_keycloak_authorization/engine.rb +8 -0
- data/lib/rails_keycloak_authorization/version.rb +3 -0
- data/lib/rails_keycloak_authorization.rb +77 -0
- data/lib/tasks/rails_keycloak_authorization_tasks.rake +170 -0
- 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,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,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,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
|