Class: Legion::CLI::Rbac

Inherits:
Thor
  • Object
show all
Defined in:
lib/legion/cli/rbac_command.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.exit_on_failure?Boolean

Returns:

  • (Boolean)


6
7
8
# File 'lib/legion/cli/rbac_command.rb', line 6

def self.exit_on_failure?
  true
end

Instance Method Details

#assign(principal, role) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/legion/cli/rbac_command.rb', line 86

def assign(principal, role)
  out = formatter
  with_data do
    record = Legion::Data::Model::RbacRoleAssignment.create(
      principal_type: options[:type],
      principal_id:   principal,
      role:           role,
      team:           options[:team],
      granted_by:     'cli',
      expires_at:     options[:expires] ? Time.parse(options[:expires]) : nil
    )
    out.success("Assigned #{role} to #{principal} (id: #{record.id})")
  end
end

#assignmentsObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/legion/cli/rbac_command.rb', line 64

def assignments
  out = formatter
  with_data do
    ds = Legion::Data::Model::RbacRoleAssignment.dataset
    ds = ds.where(team: options[:team]) if options[:team]
    ds = ds.where(role: options[:role]) if options[:role]
    ds = ds.where(principal_id: options[:principal]) if options[:principal]

    records = ds.all
    if options[:json]
      out.json(records.map(&:values))
    else
      rows = records.map { |r| [r.id, r.principal_id, r.principal_type, r.role, r.team || '-', r.active? ? 'active' : 'expired'] }
      out.table(%w[ID Principal Type Role Team Status], rows)
    end
  end
end

#check(principal_id, resource) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/legion/cli/rbac_command.rb', line 149

def check(principal_id, resource)
  out = formatter
  with_rbac do
    principal = Legion::Rbac::Principal.new(
      id:    principal_id,
      roles: options[:roles],
      team:  options[:team]
    )
    result = Legion::Rbac::PolicyEngine.evaluate(
      principal: principal,
      action:    options[:action],
      resource:  resource,
      enforce:   false
    )
    if options[:json]
      out.json(result)
    else
      status = result[:allowed] ? 'ALLOWED' : 'DENIED'
      puts "  #{status}: #{principal_id} -> #{options[:action]} #{resource}"
      puts "  Reason: #{result[:reason]}" if result[:reason]
      puts "  Would deny: #{result[:would_deny]}" if result[:would_deny]
    end
  end
end

#grant(team, pattern) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/legion/cli/rbac_command.rb', line 132

def grant(team, pattern)
  out = formatter
  with_data do
    record = Legion::Data::Model::RbacRunnerGrant.create(
      team:           team,
      runner_pattern: pattern,
      actions:        options[:actions],
      granted_by:     'cli'
    )
    out.success("Granted #{pattern} to team #{team} (id: #{record.id})")
  end
end

#grantsObject



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/legion/cli/rbac_command.rb', line 114

def grants
  out = formatter
  with_data do
    ds = Legion::Data::Model::RbacRunnerGrant.dataset
    ds = ds.where(team: options[:team]) if options[:team]

    records = ds.all
    if options[:json]
      out.json(records.map(&:values))
    else
      rows = records.map { |r| [r.id, r.team, r.runner_pattern, r.actions] }
      out.table(%w[ID Team Pattern Actions], rows)
    end
  end
end

#revoke(principal, role) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/legion/cli/rbac_command.rb', line 102

def revoke(principal, role)
  out = formatter
  with_data do
    ds = Legion::Data::Model::RbacRoleAssignment.where(principal_id: principal, role: role)
    count = ds.count
    ds.destroy
    out.success("Revoked #{count} assignment(s) of #{role} from #{principal}")
  end
end

#rolesObject



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/legion/cli/rbac_command.rb', line 16

def roles
  out = formatter
  with_rbac do
    index = Legion::Rbac.role_index
    if options[:json]
      out.json(index.transform_values { |r| { description: r.description, cross_team: r.cross_team? } })
    else
      rows = index.map { |name, r| [name.to_s, r.description, r.cross_team? ? 'yes' : 'no'] }
      out.table(%w[Role Description CrossTeam], rows)
    end
  end
end

#show(role_name) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/legion/cli/rbac_command.rb', line 31

def show(role_name)
  out = formatter
  with_rbac do
    role = Legion::Rbac.role_index[role_name.to_sym]
    unless role
      out.error("Role not found: #{role_name}")
      return
    end

    if options[:json]
      out.json({
                 name:        role.name,
                 description: role.description,
                 cross_team:  role.cross_team?,
                 permissions: role.permissions.map { |p| { resource: p.resource_pattern, actions: p.actions } },
                 deny_rules:  role.deny_rules.map { |d| { resource: d.resource_pattern, above_level: d.above_level } }
               })
    else
      out.header("Role: #{role.name}")
      puts "  #{role.description}"
      puts "  Cross-team: #{role.cross_team? ? 'yes' : 'no'}"
      puts "\n  Permissions:"
      role.permissions.each { |p| puts "    #{p.resource_pattern} -> #{p.actions.join(', ')}" }
      puts "\n  Deny rules:"
      role.deny_rules.each { |d| puts "    #{d.resource_pattern}#{" (above level #{d.above_level})" if d.above_level}" }
    end
  end
end