Commit 4d0c6c3
Changed files (4)
bin/api
@@ -80,6 +80,7 @@ end
module HTTPHelpers
def authorized?(request, permission, resource)
+ raise [permission, resource].inspect if resource.nil?
authorization = Rack::Auth::AbstractRequest.new(request.env)
return false unless authorization.provided?
@@ -138,7 +139,12 @@ class API
when "/organizations", "/organizations.json"
return json_ok(Organization.all.map(&:to_h))
when "/groups", "/groups.json"
- return json_ok(Group.all.map(&:to_h))
+ resource = Organization.default
+ if authorized?(request, :read_group, resource)
+ return json_ok(Group.all.map(&:to_h))
+ else
+ return json_unauthorized(:read_group, resource)
+ end
when "/projects", "/projects.json"
resource = Organization.default
if authorized?(request, :read_project, resource)
bin/idp
@@ -328,6 +328,7 @@ module Authz
condition(:owner) { true }
rule { owner }.enable :read_project
+ rule { owner }.enable :read_group
rule { owner }.enable :create_project
end
@@ -566,6 +567,7 @@ module Authz
<head><title></title></head>
<body>
<h2>Authorize?</h2>
+ <p>Client ID: <%= oauth_params['client_id'] %></p>
<form id="authorize-form" action="/oauth/authorize" method="post">
<input type="hidden" name="client_id" value="<%= oauth_params['client_id'] %>" />
<input type="hidden" name="scope" value="<%= oauth_params['scope'] %>" />
bin/ui
@@ -108,6 +108,10 @@ module OAuth
end
module HTTPHelpers
+ def current_user?(request)
+ request.session[:id_token]
+ end
+
def not_found
[404, { 'X-Backend-Server' => 'UI' }, []]
end
@@ -119,7 +123,6 @@ module HTTPHelpers
[302, { 'Location' => "http://ui.example.com:8080#{location}" }, []]
end
end
-
end
class UI
@@ -132,10 +135,22 @@ class UI
end
def call(env)
- path = env['PATH_INFO']
- case env['REQUEST_METHOD']
- when 'GET'
- case path
+ request = Rack::Request.new(env)
+ case request.request_method
+ when Rack::GET
+ case request.path
+ when "/groups.html"
+ if current_user?(request)
+ return get_groups(request)
+ else
+ return redirect_to("/oidc/new")
+ end
+ when /\A\/groups\/\d+\/projects.html\z/
+ if current_user?(request)
+ return get_projects(request)
+ else
+ return redirect_to("/oidc/new")
+ end
when "/oauth/callback"
return oauth_callback(Rack::Request.new(env))
when "/oidc/new"
@@ -147,8 +162,8 @@ class UI
else
return redirect_to("/saml/new")
end
- when 'POST'
- case path
+ when Rack::POST
+ case request.path
when "/saml/assertions"
return saml_assertions(Rack::Request.new(env))
else
@@ -177,7 +192,119 @@ class UI
def oauth_callback(request)
response = oauth_client.exchange(grant_type: "authorization_code", code: request.params['code'])
- [response.code, response.header, [response.body]]
+ if response.code == "200"
+ tokens = JSON.parse(response.body, symbolize_names: true)
+ request.session[:access_token] = tokens[:access_token]
+ request.session[:id_token] = tokens[:id_token]
+ request.session[:refresh_token] = tokens[:access_token]
+
+ template = <<~ERB
+ <!DOCTYPE html>
+ <html>
+ <head><title></title></head>
+ <body>
+ <pre style="display: none;"><%= response.body %></pre>
+ <pre><%= JSON.pretty_generate(request.session[:access_token]) %></pre>
+ <a href="/groups.html">Groups</a>
+ </body>
+ </html>
+ ERB
+ html = ERB.new(template, trim_mode: '-').result(binding)
+ [200, { 'Content-Type' => "text/html" }, [html]]
+ else
+ [response.code, response.header, [response.body]]
+ end
+ end
+
+ def get_groups(request)
+ http = Net::Hippie::Client.new(headers: ::Net::Hippie::Client::DEFAULT_HEADERS.merge({
+ 'Authorization' => Net::Hippie.bearer_auth(request.session[:access_token])
+ }))
+
+ response = http.get("http://api.example.com:8080/groups.json")
+ if response.code == "200"
+ groups = JSON.parse(response.body, symbolize_names: true)
+ template = <<~ERB
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <a href="/groups.html">Groups</a>
+ <table>
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>Organization ID</th>
+ <th>Parent ID</th>
+ <th> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <%- groups.each do |group| -%>
+ <tr>
+ <td><%= group[:id] %></td>
+ <td><%= group[:name] %></td>
+ <td><%= group[:organization_id] %></td>
+ <td><%= group[:parent_id] %></td>
+ <td><a href="/groups/<%= group[:id] %>/projects.html">Projects</a></td>
+ </tr>
+ <%- end -%>
+ </tbody>
+ </table>
+ </body>
+ </html>
+ ERB
+ html = ERB.new(template, trim_mode: '-').result(binding)
+ [200, { 'Content-Type' => "text/html" }, [html]]
+ else
+ [response.code, response.header, [response.body]]
+ end
+ end
+
+ def get_projects(request)
+ http = Net::Hippie::Client.new(headers: ::Net::Hippie::Client::DEFAULT_HEADERS.merge({
+ 'Authorization' => Net::Hippie.bearer_auth(request.session[:access_token])
+ }))
+
+ response = http.get("http://api.example.com:8080/projects.json")
+ if response.code == "200"
+ projects = JSON.parse(response.body, symbolize_names: true)
+
+ template = <<~ERB
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <a href="/groups.html">Groups</a>
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Group ID</th>
+ </tr>
+ </thead>
+ <tbody>
+ <%- projects.each do |project| -%>
+ <tr>
+ <td><%= project[:name] %></td>
+ <td><%= project[:group_id] %></td>
+ </tr>
+ <%- end -%>
+ </tbody>
+ </table>
+ </body>
+ </html>
+ ERB
+ html = ERB.new(template, trim_mode: '-').result(binding)
+ [200, { 'Content-Type' => "text/html" }, [html]]
+ else
+ [response.code, response.header, [response.body]]
+ end
end
def saml_post_to_idp(request)
@@ -216,7 +343,6 @@ class UI
saml_response = saml_binding.deserialize(request.params)
raise saml_response.errors unless saml_response.valid?
- request.session[:access_token] = saml_response.attributes[:access_token]
template = <<~ERB
<!doctype html>
<html>
policy.csv
@@ -9,3 +9,4 @@ p, *, idp.example.com, (GET)|(POST), /sessions*
p, *, ui.example.com, (GET)|(POST), /oauth*
p, *, ui.example.com, (GET)|(POST), /oidc*
p, *, ui.example.com, (GET)|(POST), /saml*
+p, *, ui.example.com, (GET), /*.html