Packages
ash_authentication
4.13.3
5.0.0-rc.12
5.0.0-rc.11
5.0.0-rc.10
5.0.0-rc.9
5.0.0-rc.8
5.0.0-rc.7
5.0.0-rc.6
5.0.0-rc.5
5.0.0-rc.4
5.0.0-rc.3
5.0.0-rc.2
5.0.0-rc.1
5.0.0-rc.0
4.14.1
4.14.0
4.13.7
4.13.6
4.13.5
4.13.4
4.13.3
4.13.2
retired
4.13.1
retired
4.13.0
4.12.0
4.11.0
4.10.0
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.7
4.8.6
4.8.5
4.8.3
4.8.2
4.8.1
4.8.0
4.7.6
4.7.5
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.6
4.5.5
4.5.4
4.5.3
4.5.2
4.5.1
4.5.0
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.6
4.0.0-rc.5
4.0.0-rc.3
4.0.0-rc.2
4.0.0-rc.1
4.0.0-rc.0
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.0
3.7.9
3.7.8
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.1
3.6.0
3.5.3
3.5.2
3.5.1
3.5.0
3.3.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.0
3.0.3
Authentication extension for the Ash Framework.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/add_ons/audit_log/verifier.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.AddOn.AuditLog.Verifier do
@moduledoc """
Provides configuration validation for the AuditLog add-on.
"""
alias Spark.Error.DslError
@doc false
def verify(strategy, _dsl) do
with :ok <- verify_audit_log_resource(strategy),
:ok <- verify_exclude_strategies(strategy),
:ok <- verify_exclude_actions(strategy),
:ok <- verify_truncation_masks(strategy) do
verify_sensitive_fields(strategy)
end
end
defp verify_audit_log_resource(strategy) do
cond do
!Spark.Dsl.is?(strategy.audit_log_resource, Ash.Resource) ->
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :audit_log_resource],
message: "The module `#{inspect(strategy.audit_log_resource)}` is not an Ash resource."
)}
AshAuthentication.AuditLogResource not in Spark.extensions(strategy.audit_log_resource) ->
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :audit_log_resource],
message:
"The resource `#{inspect(strategy.audit_log_resource)}` must use the `AshAuthentication.AuditLogResource` extension."
)}
true ->
:ok
end
end
defp verify_exclude_strategies(strategy) when strategy.exclude_strategies == [], do: :ok
defp verify_exclude_strategies(strategy) do
strategy.exclude_strategies
|> Enum.reject(&AshAuthentication.Info.strategy_present?(strategy.resource, &1))
|> case do
[] ->
:ok
[missing_strategy] ->
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :exclude_strategies],
message:
"The strategy or add-on `#{inspect(missing_strategy)}` is not present on the resource `#{inspect(strategy.resource)}`."
)}
missing_strategies ->
missing_strategies = Enum.map_join(missing_strategies, "\n - ", &"`#{inspect(&1)}`")
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :exclude_strategies],
message: """
The following strategies or add-ons are not present on the resource `#{inspect(strategy.resource)}`:
- #{missing_strategies}
"""
)}
end
end
defp verify_truncation_masks(strategy) do
with :ok <- verify_ipv4_mask(strategy) do
verify_ipv6_mask(strategy)
end
end
defp verify_ipv4_mask(strategy) do
mask = Map.get(strategy, :ipv4_truncation_mask, 24)
if mask >= 0 and mask <= 32 do
:ok
else
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :ipv4_truncation_mask],
message: "IPv4 truncation mask must be between 0 and 32, got #{mask}"
)}
end
end
defp verify_ipv6_mask(strategy) do
mask = Map.get(strategy, :ipv6_truncation_mask, 48)
if mask >= 0 and mask <= 128 do
:ok
else
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :ipv6_truncation_mask],
message: "IPv6 truncation mask must be between 0 and 128, got #{mask}"
)}
end
end
defp verify_exclude_actions(strategy) when strategy.exclude_actions == [], do: :ok
defp verify_exclude_actions(strategy) do
strategy.exclude_actions
|> Enum.reject(&Ash.Resource.Info.action(strategy.resource, &1))
|> case do
[] ->
:ok
[missing_action] ->
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :exclude_actions],
message:
"The action `#{inspect(missing_action)}` is not present on the resource `#{inspect(strategy.resource)}`."
)}
missing_actions ->
missing_actions = Enum.map_join(missing_actions, "\n - ", &"`#{inspect(&1)}`")
{:error,
DslError.exception(
module: strategy.resource,
path: [:authentication, :add_ons, :audit_log, strategy.name, :exclude_actions],
message: """
The following actions are not present on the resource `#{inspect(strategy.resource)}`:
- #{missing_actions}
"""
)}
end
end
defp verify_sensitive_fields(strategy) when strategy.include_fields == [], do: :ok
defp verify_sensitive_fields(strategy) do
# Find all attributes and action arguments that are sensitive
attributes = Ash.Resource.Info.attributes(strategy.resource)
actions = Ash.Resource.Info.actions(strategy.resource)
# Collect all arguments from all actions
all_arguments =
actions
|> Enum.flat_map(& &1.arguments)
|> Enum.uniq_by(& &1.name)
# Find sensitive fields that are being explicitly included
sensitive_fields_included =
strategy.include_fields
|> Enum.filter(fn field_name ->
# Check if field is a sensitive attribute
attribute_sensitive? =
attributes
|> Enum.find(&(&1.name == field_name))
|> case do
nil -> false
attr -> attr.sensitive?
end
# Check if field is a sensitive argument
argument_sensitive? =
all_arguments
|> Enum.find(&(&1.name == field_name))
|> case do
nil -> false
arg -> Map.get(arg, :sensitive?, false)
end
attribute_sensitive? || argument_sensitive?
end)
if sensitive_fields_included != [] &&
!Application.get_env(:ash_authentication, :suppress_sensitive_field_warnings?, false) do
field_list = Enum.map_join(sensitive_fields_included, ", ", &inspect/1)
IO.warn("""
AuditLog is configured to log sensitive fields: [#{field_list}]
Sensitive fields are being explicitly included in audit logs for resource #{inspect(strategy.resource)}.
This may expose sensitive user data in your audit logs.
To suppress this warning, add the following to your config:
config :ash_authentication, suppress_sensitive_field_warnings?: true
Only suppress this warning if you have verified that logging these sensitive fields is intentional and complies with your security policies.
""")
end
:ok
end
end