Class: Legion::Rbac::Middleware

Inherits:
Object
  • Object
show all
Includes:
Logging::Helper
Defined in:
lib/legion/rbac/middleware.rb

Constant Summary collapse

SKIP_PATHS =
%w[/api/health /api/ready /api/openapi.json].freeze
DEFAULT_ROUTE_PERMISSIONS =
{
  'GET /api/tasks'                       => { resource: 'tasks/*', action: :read },
  'POST /api/tasks'                      => { resource: 'tasks/*', action: :create },
  'DELETE /api/tasks/*'                  => { resource: 'tasks/*', action: :delete },
  'GET /api/workers'                     => { resource: 'workers/team', action: :read },
  'POST /api/workers'                    => { resource: 'workers/team', action: :create },
  'PATCH /api/workers/*'                 => { resource: 'workers/team', action: :lifecycle },
  'PUT /api/settings/*'                  => { resource: 'settings/*', action: :manage },
  'POST /api/transport/*'                => { resource: 'transport/*', action: :manage },
  'GET /api/events'                      => { resource: 'events/*', action: :read },
  'GET /api/events/*'                    => { resource: 'events/*', action: :read },
  'GET /api/extensions'                  => { resource: 'extensions/*', action: :read },
  'GET /api/extensions/*'                => { resource: 'extensions/*', action: :read },
  'GET /api/schedules'                   => { resource: 'schedules/*', action: :read },
  'POST /api/schedules'                  => { resource: 'schedules/*', action: :create },
  'PUT /api/schedules/*'                 => { resource: 'schedules/*', action: :update },
  'DELETE /api/schedules/*'              => { resource: 'schedules/*', action: :delete },
  'GET /api/rbac/roles'                  => { resource: 'settings/rbac', action: :read },
  'GET /api/rbac/roles/*'                => { resource: 'settings/rbac', action: :read },
  'POST /api/rbac/check'                 => { resource: 'settings/rbac', action: :read },
  'GET /api/rbac/assignments'            => { resource: 'settings/rbac', action: :read },
  'POST /api/rbac/assignments'           => { resource: 'settings/rbac', action: :manage },
  'DELETE /api/rbac/assignments/*'       => { resource: 'settings/rbac', action: :manage },
  'GET /api/rbac/grants'                 => { resource: 'settings/rbac', action: :read },
  'POST /api/rbac/grants'                => { resource: 'settings/rbac', action: :manage },
  'DELETE /api/rbac/grants/*'            => { resource: 'settings/rbac', action: :manage },
  'GET /api/rbac/grants/cross-team'      => { resource: 'settings/rbac', action: :read },
  'POST /api/rbac/grants/cross-team'     => { resource: 'settings/rbac', action: :manage },
  'DELETE /api/rbac/grants/cross-team/*' => { resource: 'settings/rbac', action: :manage }
}.freeze
INVOKE_PATTERN =
%r{\A/api/extensions/[^/]+/runners/[^/]+/functions/[^/]+/invoke\z}

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Middleware

Returns a new instance of Middleware.



45
46
47
# File 'lib/legion/rbac/middleware.rb', line 45

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/legion/rbac/middleware.rb', line 49

def call(env)
  return @app.call(env) unless Legion::Rbac.enabled?

  path = env['PATH_INFO']
  return bypass(env, path, :skip_path) if skip_path?(path)
  return bypass(env, path, :invoke_route) if invoke_route?(path)

  principal = env['legion.rbac_principal'] || env['legion.principal']
  return guard_missing(env, path, 'unauthenticated') unless principal

  perm = find_permission(env['REQUEST_METHOD'], path)
  return guard_missing(env, path, 'unmapped route') unless perm

  dispatch_policy(env, principal, effective_permission(env, perm))
rescue StandardError => e
  handle_exception(
    e,
    level:     :error,
    operation: 'rbac.middleware.call',
    method:    env['REQUEST_METHOD'],
    path:      env['PATH_INFO']
  )
  raise
end