Skip to main content
Version: 3.0

Policy

local nauthilus_policy = require("nauthilus_policy")

The nauthilus_policy module is available to request-time Lua environment and subject sources. It emits Lua-owned custom attributes into the active policy decision context.

Registry scripts also use the global nauthilus_policy.register_attribute(...) function during policy snapshot compilation. Runtime plugins use the module function documented here.

nauthilus_policy.emit_attribute​

Records one registered Lua-owned policy attribute.

Syntax​

nauthilus_policy.emit_attribute({
id = "lua.plugin.example.risky",
value = true,
details = {
status_message = "Policy violation",
},
})

Parameters​

  • id (string): Registered attribute ID.
  • value (boolean/string/number/table): Attribute value. The Lua value must match the registered attribute type.
  • details (table, optional): Detail values keyed by registered detail name.

Types​

Registry typeLua valueRuntime value
boolbooleanboolean
stringstringstring
string_listarray table of stringsstring list
numbernumbernumber
ipstringIP address
cidrstringnetwork prefix
datetimeRFC3339 stringtimestamp

Validation​

Emission fails if:

  • the attribute is not registered in the active policy snapshot;
  • the attribute is not Lua-owned;
  • the registered stage does not match the current Lua runtime stage;
  • the active operation is not listed in the registry definition;
  • the value or detail type does not match the registry definition;
  • a detail exceeds its registered max_length.

Failures abort the Lua execution like other Lua runtime errors.

Test Mode​

--test-lua provides a fixture-aware mock for nauthilus_policy.emit_attribute. The mock records emitted attributes for policy.expected_calls, but it does not build or validate a real policy snapshot. See Lua Test Framework.

Example​

Registry script:

nauthilus_policy.register_attribute({
id = "lua.plugin.geoip.rejected",
stage = "subject_analysis",
operations = { "authenticate" },
category = "environment",
type = "bool",
description = "GeoIP rejection flag",
details = {
status_message = {
type = "string",
sensitivity = "public",
purpose = "response_message",
max_length = 256,
},
},
})

Subject source script:

local nauthilus_policy = require("nauthilus_policy")

nauthilus_policy.emit_attribute({
id = "lua.plugin.geoip.rejected",
value = true,
details = {
status_message = "Policy violation",
},
})

Policy rule:

auth:
policy:
registry_scripts:
- "/etc/nauthilus/lua-plugins.d/policy/registry.lua"

policies:
- name: deny_geoip_rejection
stage: auth_decision
operations: [authenticate]
if:
attribute: lua.plugin.geoip.rejected
is: true
then:
decision: deny
response_marker: auth.response.fail
response_message:
from: attribute_detail
attribute: lua.plugin.geoip.rejected
detail: status_message
fallback: "Invalid login or password"

For the bundled plugin attributes, see Lua Policy Plugins.

Localized Policy Response Pattern​

Lua should emit stable facts, not i18n keys derived from free text. Keep nauthilus_builtin.status_message_set(...) as fallback text for existing non-localized behavior, then map the emitted fact to response_message.from: i18n in YAML.

Lua:

local policy = require("nauthilus_policy")

if account_status == "locked" then
nauthilus_builtin.status_message_set("Login failed because the account is locked.")
policy.emit_attribute({
id = "lua.company.account_status",
value = "locked",
})
end

Policy:

then:
decision: deny
response_marker: auth.response.fail
response_message:
from: i18n
i18n_key: auth.policy.company.account_locked
fallback: "Login failed because the account is locked."

Lua can also emit a language candidate:

policy.emit_attribute({
id = "lua.company.preferred_language",
value = "en",
})

Policy decides whether that value becomes response-rendering metadata:

then:
decision: deny
response_marker: auth.response.fail
response_language:
from: attribute
attribute: lua.company.preferred_language
fallback: en
response_message:
from: i18n
i18n_key: auth.policy.company.account_locked
fallback: "Login failed because the account is locked."

For complete examples, see Auth Policy I18N Guide. For Lua-owned localization helpers, see I18N.