Added auto snippet for webserver injection

This commit is contained in:
2025-08-16 01:31:49 +02:00
parent eadcb62f2a
commit f0b323afee
19 changed files with 200 additions and 37 deletions

View File

@@ -0,0 +1,56 @@
# roles/sys-srv-web-inj-compose/filter_plugins/inj_snippets.py
"""
Jinja filter: `inj_features(kind)` filters a list of features to only those
that actually provide the corresponding snippet template file.
- kind='head' -> roles/sys-srv-web-inj-<feature>/templates/head_sub.j2
- kind='body' -> roles/sys-srv-web-inj-<feature>/templates/body_sub.j2
If the feature's role directory (roles/sys-srv-web-inj-<feature>) does not
exist, this filter raises FileNotFoundError.
Usage in a template:
{% set head_features = SRV_WEB_INJ_COMP_FEATURES_ALL | inj_features('head') %}
{% set body_features = SRV_WEB_INJ_COMP_FEATURES_ALL | inj_features('body') %}
"""
import os
# This file lives at: roles/sys-srv-web-inj-compose/filter_plugins/inj_snippets.py
_THIS_DIR = os.path.dirname(__file__)
_ROLE_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..")) # roles/sys-srv-web-inj-compose
_ROLES_DIR = os.path.abspath(os.path.join(_ROLE_DIR, "..")) # roles
def _feature_role_dir(feature: str) -> str:
return os.path.join(_ROLES_DIR, f"sys-srv-web-inj-{feature}")
def _has_snippet(feature: str, kind: str) -> bool:
if kind not in ("head", "body"):
raise ValueError("kind must be 'head' or 'body'")
role_dir = _feature_role_dir(feature)
if not os.path.isdir(role_dir):
raise FileNotFoundError(
f"[inj_snippets] Expected role directory not found for feature "
f"'{feature}': {role_dir}"
)
path = os.path.join(role_dir, "templates", f"{kind}_sub.j2")
return os.path.exists(path)
def inj_features_filter(features, kind: str = "head"):
if not isinstance(features, (list, tuple)):
return []
# Validation + filtering in one pass; will raise if a role dir is missing.
valid = []
for f in features:
name = str(f)
if _has_snippet(name, kind):
valid.append(name)
return valid
class FilterModule(object):
def filters(self):
return {
"inj_features": inj_features_filter,
}

View File

@@ -39,6 +39,8 @@
- name: Reinitialize 'inj_enabled' for '{{ domain }}', after modification by CDN
set_fact:
inj_enabled: "{{ applications | inj_enabled(application_id, SRV_WEB_INJ_COMP_FEATURES_ALL) }}"
inj_head_features: "{{ SRV_WEB_INJ_COMP_FEATURES_ALL | inj_features('head') }}"
inj_body_features: "{{ SRV_WEB_INJ_COMP_FEATURES_ALL | inj_features('body') }}"
- name: "Activate Corporate CSS for '{{ domain }}'"
include_role:

View File

@@ -1,15 +1,10 @@
{# roles/sys-srv-web-inj-compose/templates/location.lua.j2 #}
{% macro push_snippets(list_name, features) -%}
{% for f in features -%}
{% if inj_enabled.get(f) -%}
{% set kind = list_name | regex_replace('_snippets$','') %}
{% for f in features if inj_enabled.get(f) -%}
{{ list_name }}[#{{ list_name }} + 1] = [=[
{%- include
'roles/sys-srv-web-inj-' ~ f ~
'/templates/' ~
('head' if list_name == 'head_snippets' else 'body') ~
'_sub.j2'
-%}
{%- include 'roles/sys-srv-web-inj-' ~ f ~ '/templates/' ~ kind ~ '_sub.j2' -%}
]=]
{% endif -%}
{% endfor -%}
{%- endmacro %}
@@ -48,7 +43,7 @@ body_filter_by_lua_block {
local whole = table.concat(ngx.ctx.buf)
ngx.ctx.buf = nil -- clear buffer
-- remove html CSP, due to management via infinito nexus policies
-- remove html CSP, due to management via Infinito.Nexus policies
whole = whole:gsub(
'<meta[^>]-http%-equiv=["\']Content%-Security%-Policy["\'][^>]->%s*',
''
@@ -57,21 +52,21 @@ body_filter_by_lua_block {
-- build a list of head-injection snippets
local head_snippets = {}
{{ push_snippets('head_snippets', ['css','matomo','desktop','javascript','logout']) }}
{{ push_snippets('head_snippets', inj_head_features) }}
-- inject all collected snippets right before </head>
local head_payload = table.concat(head_snippets, "\n") .. "</head>"
whole = string.gsub(whole, "</head>", head_payload)
whole = ngx.re.gsub(whole, "</head>", head_payload, "ijo", nil, 1)
-- build a list of body-injection snippets
local body_snippets = {}
{{ push_snippets('body_snippets', ['matomo','logout','desktop']) }}
{{ push_snippets('body_snippets', inj_body_features) }}
-- inject all collected snippets right before </body>
local body_payload = table.concat(body_snippets, "\n") .. "</body>"
whole = string.gsub(whole, "</body>", body_payload)
whole = ngx.re.gsub(whole, "</body>", body_payload, "ijo", nil, 1)
-- finally send the modified HTML out
ngx.arg[1] = whole
}
}