Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move all audit logging to templates #1709

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 0 additions & 72 deletions lib/nerves_hub/audit_logs/templates.ex

This file was deleted.

47 changes: 47 additions & 0 deletions lib/nerves_hub/audit_logs/templates/deployment_templates.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule NervesHub.AuditLogs.DeploymentTemplates do
@moduledoc """
Templates for and handling of audit logging for deployment operations.
"""
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Deployments.Deployment

@spec audit_deployment_created(User.t(), Deployment.t()) :: AuditLog.t()
def audit_deployment_created(user, deployment) do
description = "#{user.name} created deployment #{deployment.name}"
AuditLogs.audit!(user, deployment, description)
end

@spec audit_deployment_updated(User.t(), Deployment.t()) :: AuditLog.t()
def audit_deployment_updated(user, deployment) do
description = "#{user.name} updated deployment #{deployment.name}"
AuditLogs.audit!(user, deployment, description)
end

@spec audit_deployment_deleted(User.t(), Deployment.t()) :: AuditLog.t()
def audit_deployment_deleted(user, deployment) do
description = "#{user.name} deleted deployment #{deployment.name}"
AuditLogs.audit!(user, deployment, description)
end

@spec audit_deployment_toggle_active(User.t(), Deployment.t(), String.t()) :: AuditLog.t()
def audit_deployment_toggle_active(user, deployment, status) do
description = "#{user.name} marked deployment #{deployment.name} #{status}"
AuditLogs.audit!(user, deployment, description)
end

@spec audit_deployment_mismatch(Device.t(), Deployment.t(), String.t()) :: AuditLog.t()
def audit_deployment_mismatch(device, deployment, reason) do
description =
"device no longer matches deployment #{deployment.name}'s requirements because of #{reason}"

AuditLogs.audit!(device, deployment, description)
end

@spec audit_deployment_change(Deployment.t(), String.t()) :: AuditLog.t()
def audit_deployment_change(deployment, change_string) do
description = "deployment #{deployment.name} #{change_string}"
AuditLogs.audit!(deployment, deployment, description)
end
end
124 changes: 124 additions & 0 deletions lib/nerves_hub/audit_logs/templates/device_templates.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
defmodule NervesHub.AuditLogs.DeviceTemplates do
@moduledoc """
Templates for and handling of audit logging for device operations.
"""
alias NervesHub.Firmwares.Firmware
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.Device

require Logger

## General

@spec audit_reboot(User.t(), Device.t()) :: AuditLog.t()
def audit_reboot(user, device) do
description = "#{user.name} rebooted device #{device.identifier}"
AuditLogs.audit!(user, device, description)
end

@spec audit_request_action(User.t(), Device.t(), String.t()) :: AuditLog.t()
def audit_request_action(user, device, action) do
description = "#{user.name} requested the device (#{device.identifier}) #{action}"
AuditLogs.audit!(user, device, description)
end

@spec audit_unsupported_api_version(Device.t()) :: AuditLog.t()
def audit_unsupported_api_version(device) do
description =
"device #{device.identifier} could not get extensions: Unsupported API version."

AuditLogs.audit!(device, device, description)
Logger.info("[DeviceChannel] #{description}")
end

## Firmware and upgrades

@spec audit_update_attempt(Device.t()) :: AuditLog.t()
def audit_update_attempt(device) do
description = "device #{device.identifier} is attempting to update"
AuditLogs.audit(device, device, description)
end

@spec audit_pushed_available_update(User.t(), Device.t(), Deployment.t()) :: AuditLog.t()
def audit_pushed_available_update(user, device, deployment) do
description =
"#{user.name} pushed available firmware update #{deployment.firmware.version} #{deployment.firmware.uuid} to device #{device.identifier}"

AuditLogs.audit!(user, device, description)
end

@spec audit_firmware_pushed(User.t(), Device.t(), Firmware.t()) :: AuditLog.t()
def audit_firmware_pushed(user, device, firmware) do
description =
"#{user.name} pushed firmware #{firmware.version} #{firmware.uuid} to device #{device.identifier}"

AuditLogs.audit!(user, device, description)
end

@spec audit_firmware_metadata_updated(Device.t()) :: AuditLog.t()
def audit_firmware_metadata_updated(device) do
description = "device #{device.identifier} updated firmware metadata"
AuditLogs.audit!(device, device, description)
end

@spec audit_firmware_upgrade_blocked(Deployment.t(), Device.t()) :: AuditLog.t()
def audit_firmware_upgrade_blocked(deployment, device) do
description = """
Device #{device.identifier} automatically blocked firmware upgrades for #{deployment.penalty_timeout_minutes} minutes.
Device failure rate met for firmware #{deployment.firmware.uuid} in deployment #{deployment.name}.
"""

AuditLogs.audit!(deployment, device, description)
end

@spec audit_firmware_updated(Device.t()) :: AuditLog.t()
def audit_firmware_updated(device) do
description =
"device #{device.identifier} firmware set to version #{device.firmware_metadata.version} (#{device.firmware_metadata.uuid})"

AuditLogs.audit!(device, device, description)
end

@spec audit_device_deployment_update_triggered(Device.t(), UUIDv7.t()) :: AuditLog.t()
def audit_device_deployment_update_triggered(device, reference_id) do
deployment = device.deployment
firmware = deployment.firmware

description =
"deployment #{deployment.name} update triggered device #{device.identifier} to update firmware #{firmware.uuid}"

AuditLogs.audit_with_ref!(deployment, device, description, reference_id)
end

@spec audit_device_deployment_update(User.t(), Device.t(), Deployment.t()) :: AuditLog.t()
def audit_device_deployment_update(user, device, deployment) do
AuditLogs.audit!(
user,
device,
"#{user.name} set #{device.identifier}'s deployment to #{deployment.name}"
)
end

@spec audit_device_deployment_update(Device.t(), Deployment.t(), :one_found | :multiple_found) ::
AuditLog.t()
def audit_set_deployment(device, deployment, :one_found) do
AuditLogs.audit!(
device,
device,
"Updating #{device.identifier}'s deployment to #{deployment.name}"
)
end

@spec audit_set_deployment(Device.t(), Deployment.t(), :one_found | :multiple_found) ::
AuditLog.t()
def audit_set_deployment(device, deployment, :multiple_found) do
AuditLogs.audit!(
device,
device,
"Multiple matching deployments found, updating #{device.identifier}'s deployment to #{deployment.name}"
)
end
end
25 changes: 8 additions & 17 deletions lib/nerves_hub/deployments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ defmodule NervesHub.Deployments do

require Logger

alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.Templates
alias NervesHub.AuditLogs.DeploymentTemplates
alias NervesHub.AuditLogs.DeviceTemplates
alias NervesHub.Deployments.Deployment
alias NervesHub.Deployments.InflightDeploymentCheck
alias NervesHub.Devices
Expand Down Expand Up @@ -183,16 +183,13 @@ defmodule NervesHub.Deployments do
payload = %{archive_id: archive_id}
_ = broadcast(deployment, "archives/updated", payload)

description = "deployment #{deployment.name} has a new archive"
AuditLogs.audit!(deployment, deployment, description)
DeploymentTemplates.audit_deployment_change(deployment, "has a new archive")

{:conditions, _new_conditions} ->
description = "deployment #{deployment.name} conditions changed"
AuditLogs.audit!(deployment, deployment, description)
DeploymentTemplates.audit_deployment_change(deployment, "conditions changed")

{:is_active, is_active} when is_active != true ->
description = "deployment #{deployment.name} is inactive"
AuditLogs.audit!(deployment, deployment, description)
DeploymentTemplates.audit_deployment_change(deployment, "is inactive")

_ ->
:ignore
Expand Down Expand Up @@ -336,13 +333,7 @@ defmodule NervesHub.Deployments do
|> Ecto.Changeset.change(%{deployment_id: nil})
|> Repo.update!()

AuditLogs.audit!(
device,
device,
"device no longer matches deployment #{deployment.name}'s requirements because of #{reason}"
)

device
DeploymentTemplates.audit_deployment_mismatch(device, deployment, reason)
else
device
end
Expand All @@ -366,7 +357,7 @@ defmodule NervesHub.Deployments do
[deployment] ->
set_deployment_telemetry(:one_found, device, deployment)

Templates.audit_set_deployment(device, deployment, :one_found)
DeviceTemplates.audit_set_deployment(device, deployment, :one_found)

device
|> Devices.update_deployment(deployment)
Expand All @@ -375,7 +366,7 @@ defmodule NervesHub.Deployments do
[deployment | _] ->
set_deployment_telemetry(:multiple_found, device, deployment)

Templates.audit_set_deployment(device, deployment, :multiple_found)
DeviceTemplates.audit_set_deployment(device, deployment, :multiple_found)

device
|> Devices.update_deployment(deployment)
Expand Down
26 changes: 6 additions & 20 deletions lib/nerves_hub/devices.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule NervesHub.Devices do
alias NervesHub.Accounts.OrgKey
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.DeviceTemplates
alias NervesHub.Certificate
alias NervesHub.Deployments.Deployment
alias NervesHub.Deployments.Orchestrator
Expand Down Expand Up @@ -791,8 +792,7 @@ defmodule NervesHub.Devices do
end

def update_firmware_metadata(device, metadata) do
description = "device #{device.identifier} updated firmware metadata"
AuditLogs.audit!(device, device, description)
DeviceTemplates.audit_firmware_metadata_updated(device)
update_device(device, %{firmware_metadata: metadata})
end

Expand Down Expand Up @@ -942,12 +942,7 @@ defmodule NervesHub.Devices do
|> DateTime.truncate(:second)
|> DateTime.add(deployment.penalty_timeout_minutes * 60, :second)

description = """
Device #{device.identifier} automatically blocked firmware upgrades for #{deployment.penalty_timeout_minutes} minutes.
Device failure rate met for firmware #{deployment.firmware.uuid} in deployment #{deployment.name}.
"""

AuditLogs.audit!(deployment, device, description)
DeviceTemplates.audit_firmware_upgrade_blocked(deployment, device)
clear_inflight_update(device)

{:ok, device} = update_device(device, %{updates_blocked_until: blocked_until})
Expand All @@ -960,12 +955,7 @@ defmodule NervesHub.Devices do
|> DateTime.truncate(:second)
|> DateTime.add(deployment.penalty_timeout_minutes * 60, :second)

description = """
Device #{device.identifier} automatically blocked firmware upgrades for #{deployment.penalty_timeout_minutes} minutes.
Device failure threshold met for firmware #{deployment.firmware.uuid} in deployment #{deployment.name}.
"""

AuditLogs.audit!(deployment, device, description)
DeviceTemplates.audit_firmware_upgrade_blocked(deployment, device)
clear_inflight_update(device)

{:ok, device} = update_device(device, %{updates_blocked_until: blocked_until})
Expand All @@ -988,8 +978,7 @@ defmodule NervesHub.Devices do
Multi.new()
|> Multi.update(:device, changeset)
|> Multi.run(:audit_device, fn _, _ ->
description = "device #{device.identifier} is attempting to update"
AuditLogs.audit(device, device, description)
DeviceTemplates.audit_update_attempt(device)
end)
|> Repo.transaction()
|> case do
Expand All @@ -1007,10 +996,7 @@ defmodule NervesHub.Devices do
firmware_uuid: device.firmware_metadata.uuid
})

description =
"device #{device.identifier} firmware set to version #{device.firmware_metadata.version} (#{device.firmware_metadata.uuid})"

AuditLogs.audit!(device, device, description)
DeviceTemplates.audit_firmware_updated(device)

# Clear the inflight update, no longer inflight!
inflight_update =
Expand Down
Loading
Loading