Module: CommandTower::Authorization

Defined in:
lib/command_tower/authorization.rb,
lib/command_tower/authorization/role.rb,
lib/command_tower/authorization/entity.rb,
lib/command_tower/authorization/assignable_roles.rb,
lib/command_tower/authorization/effective_entity_grants.rb

Defined Under Namespace

Modules: AssignableRoles, EffectiveEntityGrants Classes: Entity, Error, Role

Constant Summary collapse

SOURCE_COMMAND_TOWER =
:command_tower
SOURCE_HOST =
:host

Class Method Summary collapse

Class Method Details

.add_mapping!(role:) ⇒ Object



24
25
26
27
28
29
# File 'lib/command_tower/authorization.rb', line 24

def add_mapping!(role:)
  role.guards.each do |controller, methods|
    mapped_controllers[controller] ||= Set.new
    mapped_controllers[controller] += methods
  end
end

.default_defined!(validate: true) ⇒ Object



41
42
43
44
45
46
# File 'lib/command_tower/authorization.rb', line 41

def default_defined!(validate: true)
  reset_graph!
  provision_rbac_default!
  provision_rbac_user_defined!
  validate_composed_graph! if validate
end

.load_yaml(path) ⇒ Object



60
61
62
63
64
# File 'lib/command_tower/authorization.rb', line 60

def load_yaml(path)
  return nil unless File.exist?(path)

  YAML.load_file(path)
end

.mapped_controllersObject



20
21
22
# File 'lib/command_tower/authorization.rb', line 20

def mapped_controllers
  @mapped_controllers ||= {}
end

.mapped_controllers_reset!Object



31
32
33
# File 'lib/command_tower/authorization.rb', line 31

def mapped_controllers_reset!
  @mapped_controllers = {}
end

.provision_rbac_default!Object



54
55
56
57
58
# File 'lib/command_tower/authorization.rb', line 54

def provision_rbac_default!
  path = CommandTower::Engine.root.join("lib", "command_tower", "authorization", "default.yml")
  rbac_configuration = load_yaml(path)
  provision_rbac_via_yaml(rbac_configuration, source: SOURCE_COMMAND_TOWER)
end

.provision_rbac_user_defined!Object



48
49
50
51
52
# File 'lib/command_tower/authorization.rb', line 48

def provision_rbac_user_defined!
  path = CommandTower.config.authorization.rbac_group_path
  rbac_configuration = load_yaml(path)
  provision_rbac_via_yaml(rbac_configuration, source: SOURCE_HOST)
end

.provision_rbac_via_yaml(rbac_configuration, source:) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/command_tower/authorization.rb', line 66

def provision_rbac_via_yaml(rbac_configuration, source:)
  return if rbac_configuration.nil?

  unless rbac_configuration.is_a?(Hash)
    raise Error, "RBAC source must be a mapping (got #{rbac_configuration.class})"
  end

  entity_rows = rbac_configuration["entities"]
  if !entity_rows.nil? && !entity_rows.is_a?(Array)
    raise Error, "RBAC entities must be a list"
  end

  Array(entity_rows).each do |entity|
    raise Error, "RBAC entity definition must be a mapping" unless entity.is_a?(Hash)
    raise Error, "RBAC entity is missing name" if entity["name"].blank?

    CommandTower::Authorization::Entity.create_entity(
      name: entity["name"],
      controller: entity["controller"],
      only: entity["only"],
      except: entity["except"],
      source: source,
    )
  end

  groups = rbac_configuration["groups"]
  return if groups.nil?

  unless groups.is_a?(Hash)
    raise Error, "RBAC groups must be a mapping"
  end

  groups.each do |name, |
    raise Error, "RBAC group [#{name}] must be a mapping" unless .is_a?(Hash)

    description = ["description"]
    allow_everything = false
    entities = nil

    if ["entities"] == true
      allow_everything = true
    else
      grant_names = Array(["entities"])
      entities = grant_names.map do |grant_name|
        resolved = CommandTower::Authorization::Entity.entities[grant_name]
        if resolved.nil?
          raise Error, "RBAC group [#{name}] references unknown entity [#{grant_name}]"
        end
        resolved
      end
    end

    CommandTower::Authorization::Role.create_role(
      name:,
      entities:,
      description:,
      allow_everything:,
      source: source,
    )
  end
end

.reset_graph!Object



35
36
37
38
39
# File 'lib/command_tower/authorization.rb', line 35

def reset_graph!
  CommandTower::Authorization::Role.roles_reset!
  CommandTower::Authorization::Entity.entities_reset!
  mapped_controllers_reset!
end

.validate_composed_graph!Object



128
129
130
# File 'lib/command_tower/authorization.rb', line 128

def validate_composed_graph!
  validate_default_membership_role!
end

.validate_default_membership_role!Object

Raises:



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/command_tower/authorization.rb', line 132

def validate_default_membership_role!
  role_name = CommandTower.config.authorization.default_membership_role
  return if role_name.nil?

  if role_name.to_s.strip.empty?
    raise Error, "authorization.default_membership_role is blank; use nil to disable default assignment"
  end

  return if CommandTower::Authorization::Role.roles[role_name]

  raise Error,
    "authorization.default_membership_role [#{role_name}] is not present in the composed RBAC graph"
end