AshAuthentication.AddOn.AuditLog.IpPrivacy (ash_authentication v4.15.0)
View SourceProvides IP address privacy transformations for audit logging.
The audit log add-on transforms client IP addresses with this module before it
writes them. Select the transformation with the ip_privacy_mode option of the
audit_log add-on.
Modes
:none- store the address unchanged. This is the default.:truncate- keep the network prefix of the address and drop the host part.:exclude- do not store the address at all.:hash- store a keyed digest of the address.
The :hash mode
:hash computes an HMAC-SHA256 of the address under a salt which you must
configure, then keeps the first 64 bits of the result:
config :my_app, audit_log_ip_salt: System.fetch_env!("AUDIT_LOG_IP_SALT")The salt can be a string, or a {module, function, arguments} tuple which
returns a string. The add-on reads it from the application which owns the
resource being audited, so each application in an umbrella has its own salt.
Deprecated salt locations
Earlier versions read the salt from this library's own application name. Both
config :ash_authentication, audit_log_ip_salt: ... and
config :ash_authentication, secret: ... still work, and are used when the
owning application configures nothing. Both are deprecated, both warn at start
up, and both will be removed in a future release.
Run mix ash_authentication.upgrade to move the setting. Keep the value
identical: a different salt changes every stored digest, so entries written
before the move stop correlating with entries written after it.
The salt must be secret and it must have high entropy. IPv4 has only 2^32
addresses, so anybody who knows the salt can compute the digest of every
address and reverse the stored values. There is no salt which is safe to share
between deployments, and there is no safe default. :hash therefore fails
closed: AshAuthentication.Supervisor refuses to start when a resource selects
:hash without a salt, and hash_ip/1 raises for the same reason.
A digest still identifies one address, which lets you count the events which
come from it. Use :truncate or :exclude when you do not need that.
Neither depends on a secret, so neither can fail in this way.
Hashing is not anonymisation. A digest of an IP address remains personal data under the GDPR and similar laws, because it still singles out one subscriber. Protect the stored digests the same way you would protect the raw addresses.
Summary
Functions
Apply privacy transformation to an IP address string.
Apply privacy transformation to request data containing IP addresses.
Hash an IP address with the configured salt.
Truncate an IP address to a network prefix.
Check the given resources for an audit log add-on which hashes IP addresses without a configured salt.
Functions
Apply privacy transformation to an IP address string.
Options
:mode- The privacy mode (:none,:hash,:truncate,:exclude):truncation_masks- Map with:ipv4and:ipv6keys for truncation bits:otp_app- The application whose configuration holds the hash salt. Only used by:hash.
Apply privacy transformation to request data containing IP addresses.
Transforms the following fields:
remote_ipx_forwarded_for(list of IPs)forwarded(list of forwarded headers)
Hash an IP address with the configured salt.
Computes an HMAC-SHA256 of the address and keeps the first 64 bits of the digest.
Raises when no salt is configured. See the module documentation for the reason and for the configuration keys.
Truncate an IP address to a network prefix.
For IPv4: Applies a subnet mask (e.g., /24 keeps first 3 octets) For IPv6: Applies a prefix length (e.g., /48 keeps first 3 hextets)
@spec verify_hash_salt!(atom() | nil, [Ash.Resource.t()]) :: :ok
Check the given resources for an audit log add-on which hashes IP addresses without a configured salt.
Raises when it finds one. AshAuthentication.Supervisor calls this when it
starts, so a deployment which is missing the salt fails to boot instead of
writing reversible digests.
Warns when the salt only resolves from the deprecated :ash_authentication
configuration.