},
"description": "Tags to link with other policy rules.",
"default": null
+ },
+ "log": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string",
+ "enum": [
+ "ip",
+ "name"
+ ]
+ },
+ "description": "Enables logging information whenever this RPZ matches.",
+ "default": null
}
}
},
Optional, restrict when this RPZ applies. See :ref:`config-policy-new-tags`.
+ .. option:: log: <list, subset of [ name, ip ]>
+
+ Optional, indicate that each application of a rule should log the domain name
+ triggering it and/or the requestor's IP.
+ Logging is then done at the *notice* level.
+
+ .. code-block::
+
+ [rules ] => local data applied, user: ::1, name: foo.bar.93.100.in-addr.arpa.
+
+ .. option:: dry-run: <boolean, false by default>
+
+ Do not apply these rules. You want to combine this with ``log``.
+
.. code-block:: yaml
local-data:
rpz:
- file: /tmp/adult.rpz
tags: [ adult ]
- # security blocklist applied for everyone
+ # security blocklist applied for everyone
- file: /tmp/security.rpz
+ # log these but do not block them
+ - file: /tmp/suspicious.rpz
+ dry-run: true
+ log: [ name, ip ]
So far, RPZ support is limited to the most common features:
tags: Optional[List[IDPattern]] = None
ttl: Optional[TimeUnit] = None
nodata: Optional[bool] = None
+ # TODO: probably also implement the rule options from RPZSchema (.log + .dry_run)
def _validate(self) -> None:
options_sum = sum([bool(self.address), bool(self.subtree), bool(self.file), bool(self.records)])
file: Path to the RPZ zone file.
watchdog: Enables files watchdog for configured RPZ file. Requires the optional 'watchdog' dependency.
tags: Tags to link with other policy rules.
+ log: Enables logging information whenever this RPZ matches.
"""
file: ReadableFile
watchdog: Union[Literal["auto"], bool] = "auto"
tags: Optional[List[IDPattern]] = None
+ log: Optional[List[Literal["ip", "name"]]] = None
+ dry_run: bool = False
_LAYER = Raw
file: ReadableFile
watchdog: bool
tags: Optional[List[IDPattern]]
+ log: Optional[List[Literal["ip", "name"]]]
+ dry_run: bool
def _watchdog(self, obj: Raw) -> Any:
if obj.watchdog == "auto":
{# records #}
{% if cfg.local_data.records -%}
-{{ local_data_records(cfg.local_data.records, false, cfg.local_data.nodata, cfg.local_data.ttl) }}
+{{ local_data_records(cfg.local_data.records, false, cfg.local_data.nodata, cfg.local_data.ttl, none) }}
{%- endif %}
{# rules #}
{# rpz #}
{% if cfg.local_data.rpz -%}
{% for rpz in cfg.local_data.rpz %}
-{{ local_data_records(rpz.file, true, cfg.local_data.nodata, cfg.local_data.ttl, rpz.tags) }}
+{{ local_data_records(rpz.file, true, cfg.local_data.nodata, cfg.local_data.ttl, rpz) }}
{% endfor %}
{%- endif %}
{%- endmacro %}
-{% macro local_data_records(input_str, is_rpz, nodata, ttl, tags=none, id='rrs') -%}
+{% macro local_data_records(input_str, is_rpz, nodata, ttl, extra, id='rrs') -%}
{{ id }} = ffi.new('struct kr_rule_zonefile_config')
{{ id }}.ttl = {{ local_data_ttl(ttl) }}
-{{ id }}.tags = {{ policy_get_tagset(tags) }}
+{{ id }}.tags = {{ policy_get_tagset(extra.tags) }}
{{ id }}.nodata = {{ boolean(nodata) }}
{{ id }}.is_rpz = {{ boolean(is_rpz) }}
-{{ id }}.opts = C.KR_RULE_OPTS_DEFAULT
{% if is_rpz -%}
{{ id }}.filename = '{{ input_str }}'
{% else %}
{{ input_str.multiline() }}
]]
{% endif %}
+{# .opts are complicated #}
+{{ id }}.opts = C.KR_RULE_OPTS_DEFAULT
+{% if extra is not none -%}
+{% if extra.dry_run is not none and extra.dry_run -%}
+{{ id }}.opts.score = 4
+{% else %}
+{{ id }}.opts.score = 9
+{% endif %}
+{% if extra.log is not none -%}
+{{ id }}.opts.log_level = 3 -- notice
+{% endif %}
+{% if extra.log is not none and 'ip' in extra.log -%}
+{{ id }}.opts.log_ip = true
+{% endif %}
+{% if extra.log is not none and 'name' in extra.log -%}
+{{ id }}.opts.log_name = true
+{% endif %}
+{% endif %}
assert(C.kr_rule_zonefile({{ id }})==0)
{%- endmacro %}
{{ kr_rule_local_hosts(file, nodata if item.nodata is none else item.nodata, item.ttl or ttl, item.tags) }}
{% endfor %}
{% elif item.records %}
-{{ local_data_records(item.records, false, nodata if item.nodata is none else item.nodata, item.ttl or ttl, item.tags) }}
+{{ local_data_records(item.records, false, nodata if item.nodata is none else item.nodata, item.ttl or ttl, item) }}
{% endif %}
{% endfor %}
{%- endmacro %}