Files
ubicloud/routes/project/location/private_subnet.rb
Jeremy Evans 8cada58820 Add audit logging to all route actions
Audit logging is designed to be simple to use.  You call the audit_log
method with the object affected and the action taken on it:

```ruby
audit_log(vm, "create")
```

If additional objects are affected by the same action, then you can
include them in the third argument:

```ruby
audit_log(ps, "connect", subnet)
```

This implements an audit logging check similar to the recently
added authorization check.  All successful non-GET requests to the
application are checked for audit logging, and will fail in
non-frozen tests if an audit logging method is not called.

Currently, only create/destroy actions are logged.  Audit logging
in other cases is ignored.  However, this approach was necessary
to check that no cases that should result in audit logging were
missed. It also allows for easily flipping the switch to audit log
all route actions.
2025-05-13 06:38:49 +09:00

109 lines
3.3 KiB
Ruby

# frozen_string_literal: true
class Clover
hash_branch(:project_location_prefix, "private-subnet") do |r|
r.get api? do
private_subnet_list
end
r.on PRIVATE_SUBNET_NAME_OR_UBID do |ps_name, ps_id|
if ps_name
r.post true do
check_visible_location
private_subnet_post(ps_name)
end
filter = {Sequel[:private_subnet][:name] => ps_name}
else
filter = {Sequel[:private_subnet][:id] => UBID.to_uuid(ps_id)}
end
filter[:location_id] = @location.id
ps = @project.private_subnets_dataset.eager(:location).first(filter)
check_found_object(ps)
r.post "connect" do
authorize("PrivateSubnet:connect", ps.id)
subnet = PrivateSubnet.from_ubid(r.params["connected-subnet-id"])
unless subnet
if api?
response.status = 400
next {error: {code: 400, type: "InvalidRequest", message: "Subnet to be connected not found"}}
else
flash["error"] = "Subnet to be connected not found"
r.redirect "#{@project.path}#{ps.path}"
end
end
authorize("PrivateSubnet:connect", subnet.id)
DB.transaction do
ps.connect_subnet(subnet)
audit_log(ps, "connect", subnet)
end
if api?
Serializers::PrivateSubnet.serialize(ps)
else
flash["notice"] = "#{subnet.name} will be connected in a few seconds"
r.redirect "#{@project.path}#{ps.path}"
end
end
r.post "disconnect", String do |disconnecting_ps_ubid|
authorize("PrivateSubnet:disconnect", ps.id)
subnet = PrivateSubnet.from_ubid(disconnecting_ps_ubid)
unless subnet
response.status = 400
next {error: {code: 400, type: "InvalidRequest", message: "Subnet to be disconnected not found"}}
end
authorize("PrivateSubnet:disconnect", subnet.id)
DB.transaction do
ps.disconnect_subnet(subnet)
audit_log(ps, "disconnect", subnet)
end
if api?
Serializers::PrivateSubnet.serialize(ps)
else
flash["notice"] = "#{subnet.name} will be disconnected in a few seconds"
204
end
end
request.get true do
authorize("PrivateSubnet:view", ps.id)
@ps = Serializers::PrivateSubnet.serialize(ps)
if api?
@ps
else
@nics = Serializers::Nic.serialize(ps.nics)
@connected_subnets = Serializers::PrivateSubnet.serialize(ps.connected_subnets)
connectable_subnets = ps.project.private_subnets.select do |ps1|
ps1_id = ps1.id
ps1_id != ps.id && !ps.connected_subnets.find { |cs| cs.id == ps1_id }
end
@connectable_subnets = Serializers::PrivateSubnet.serialize(connectable_subnets)
view "networking/private_subnet/show"
end
end
request.delete true do
authorize("PrivateSubnet:delete", ps.id)
unless ps.vms.all? { it.destroy_set? || it.strand.nil? || it.strand.label == "destroy" }
fail DependencyError.new("Private subnet '#{ps.name}' has VMs attached, first, delete them.")
end
DB.transaction do
ps.incr_destroy
audit_log(ps, "destroy")
end
204
end
end
end
end