Commit 1faacf8
Changed files (5)
lib
authx
bin/api
@@ -7,6 +7,7 @@ gemfile do
gem "declarative_policy", "~> 1.0"
gem "erb", "~> 4.0"
+ gem "globalid", "~> 1.0"
gem "google-protobuf", "~> 3.0"
gem "json", "~> 2.0"
gem "logger", "~> 1.0"
@@ -26,6 +27,16 @@ $scheme = ENV.fetch("SCHEME", "http")
$port = ENV.fetch("PORT", 8284).to_i
$host = ENV.fetch("HOST", "localhost:#{$port}")
+class Organization
+ def initialize(attributes = {})
+ @attributes = attributes
+ end
+
+ def id
+ @attributes[:id]
+ end
+end
+
class Project
class << self
def all
@@ -49,6 +60,12 @@ class Project
end
class API
+ attr_reader :rpc
+
+ def initialize
+ @rpc = ::Authx::Rpc::AbilityClient.new("http://idp.example.com:8080/twirp")
+ end
+
def call(env)
request = Rack::Request.new(env)
path = env['PATH_INFO']
@@ -77,13 +94,17 @@ class API
private
- def authorized?(request, permission)
+ def authorized?(request, permission, resource = Organization.new(id: 1))
# TODO:: Check the JWT for the appropriate claim
# Connect to the Authz RPC endpoint Ability.allowed?(subject, permission, resource)
- client = ::Authx::Rpc::AbilityClient.new("http://idp.example.com:8080/twirp")
- response = client.allowed(subject: "", permission: permission, resource: "")
+ token = request&.get_header('HTTP_AUTHORIZATION')&.split(' ', 2)&.last
+ response = rpc.allowed(
+ subject: token,
+ permission: permission,
+ resource: ::GlobalID.create(resource, app: "example").to_s
+ )
puts response.inspect
- response&.error&.nil? && response&.data&.result
+ response.error.nil? && response.data.result
end
def json_not_found
bin/e2e
@@ -19,6 +19,6 @@ $BROWSER http://ui.example.com:8080/saml/new
$BROWSER http://ui.example.com:8080/oidc/new
curl http://api.example.com:8080/projects.json
-curl -i -XPOST http://api.example.com:8080/projects --data '{"name": "gitlab"}'
+curl -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2YmYxZTlmMy02OGIwLTQ4NmYtOGVlZi0wODFmZTg2YjJlODMiLCJpYXQiOjE3NDEyOTAzMzJ9.e30=' -XPOST http://api.example.com:8080/projects --data '{"name": "gitlab"}'
curl http://api.example.com:8080/projects.json
bin/idp
@@ -6,8 +6,9 @@ gemfile do
source "https://rubygems.org"
gem "declarative_policy", "~> 1.0"
- gem "google-protobuf", "~> 3.0"
gem "erb", "~> 4.0"
+ gem "globalid", "~> 1.0"
+ gem "google-protobuf", "~> 3.0"
gem "rack", "~> 3.0"
gem "rackup", "~> 2.0"
gem "saml-kit", "~> 1.0"
lib/authx/rpc/ability_handler.rb
@@ -1,10 +1,19 @@
# frozen_string_literal: true
+class Organization
+ class << self
+ def find(id)
+ new
+ end
+ end
+end
+
module Authx
module Rpc
+
class AbilityHandler
def allowed(request, env)
- puts [request, env].inspect
+ puts [request, env, can?(request)].inspect
{
result: can?(request)
@@ -14,12 +23,27 @@ module Authx
private
def can?(request)
- policy_for(request).can?(request.permission)
+ subject = subject_of(request.subject)
+ resource = resource_from(request.resource)
+ policy = DeclarativePolicy.policy_for(subject, resource)
+ policy.can?(request.permission.to_sym)
+ end
+
+ def subject_of(token)
+ _header, claims, _signature = from_jwt(token)
+ claims[:sub]
+ end
+
+ def resource_from(global_id)
+ # TODO:: Parse global id and convert to class
+ GlobalID::Locator.locate(global_id)
end
- def policy_for(request)
- # TODO:: convert subject in form of GlobalID to Resource Type
- DeclarativePolicy.policy_for(request.subject, request.resource)
+ # TODO:: validate signature
+ def from_jwt(token)
+ token
+ .split('.', 3)
+ .map { |x| JSON.parse(Base64.strict_decode64(x), symbolize_names: true) }
end
end
end
lib/authx.rb
@@ -5,9 +5,15 @@ require "declarative_policy"
require "authx/rpc"
module Authx
- class ProjectPolicy < DeclarativePolicy::Base
+ class OrganizationPolicy < DeclarativePolicy::Base
condition(:owner) { true }
rule { owner }.enable :create_project
end
+
+ DeclarativePolicy.configure do
+ name_transformation do |name|
+ "Authx::#{name}Policy"
+ end
+ end
end