mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2026-03-17 14:26:18 +00:00
refactor Caddyfile generation to improve policy handling and cookie collection
This commit is contained in:
@@ -73,6 +73,12 @@ def collect_all_applications():
|
|||||||
def build_caddyfile(apps, auth_policies, routes):
|
def build_caddyfile(apps, auth_policies, routes):
|
||||||
lines = []
|
lines = []
|
||||||
has_authelia = auth_policies is not None
|
has_authelia = auth_policies is not None
|
||||||
|
policies = auth_policies.get("policies", {}) if has_authelia else {}
|
||||||
|
|
||||||
|
def get_policy_type(policy_name):
|
||||||
|
if policy_name and policy_name in policies:
|
||||||
|
return policies[policy_name].get("policy_type", "bypass")
|
||||||
|
return "bypass"
|
||||||
|
|
||||||
for app in apps:
|
for app in apps:
|
||||||
app_id = app.get("id", "unknown")
|
app_id = app.get("id", "unknown")
|
||||||
@@ -116,27 +122,61 @@ def build_caddyfile(apps, auth_policies, routes):
|
|||||||
for route in app_route_data.get("routes", []):
|
for route in app_route_data.get("routes", []):
|
||||||
app_routes[route.get("path_prefix", "")] = route.get("policy", "")
|
app_routes[route.get("path_prefix", "")] = route.get("policy", "")
|
||||||
|
|
||||||
|
default_policy_type = get_policy_type(app_default_policy)
|
||||||
|
|
||||||
|
# When the default policy is deny, use handle blocks for specific
|
||||||
|
# non-deny routes and a catch-all respond 403 at Caddy level,
|
||||||
|
# avoiding an unnecessary Authelia round-trip.
|
||||||
|
if has_authelia and default_policy_type == "deny":
|
||||||
|
for path_prefix, policy_name in app_routes.items():
|
||||||
|
ptype = get_policy_type(policy_name)
|
||||||
|
if ptype == "bypass":
|
||||||
|
lines.append(f" handle {path_prefix}/* {{")
|
||||||
|
lines.append(f" reverse_proxy {upstream}")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append("")
|
||||||
|
elif ptype == "deny":
|
||||||
|
lines.append(f" handle {path_prefix}/* {{")
|
||||||
|
lines.append(f" respond 403")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append("")
|
||||||
|
else:
|
||||||
|
lines.append(f" handle {path_prefix}/* {{")
|
||||||
|
lines.append(f" forward_auth {AUTHELIA_INTERNAL_URL} {{")
|
||||||
|
lines.append(f" uri {AUTHELIA_PORTAL_PATH}/api/authz/forward-auth")
|
||||||
|
lines.append(f" copy_headers Remote-User Remote-Groups Remote-Name Remote-Email")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append(f" reverse_proxy {upstream}")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append("")
|
||||||
|
lines.append(f" respond 403")
|
||||||
|
lines.append(f"}}")
|
||||||
|
lines.append("")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# For bypass/protected default policy: emit explicit deny blocks for
|
||||||
|
# any per-route deny entries before the forward_auth check.
|
||||||
|
for path_prefix, policy_name in app_routes.items():
|
||||||
|
if get_policy_type(policy_name) == "deny":
|
||||||
|
lines.append(f" handle {path_prefix}/* {{")
|
||||||
|
lines.append(f" respond 403")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
needs_auth = False
|
needs_auth = False
|
||||||
if has_authelia and auth_policies:
|
if has_authelia and auth_policies:
|
||||||
policies = auth_policies.get("policies", {})
|
if default_policy_type not in ("bypass", "deny"):
|
||||||
if app_default_policy and app_default_policy in policies:
|
needs_auth = True
|
||||||
policy_data = policies[app_default_policy]
|
|
||||||
if policy_data.get("policy_type") != "bypass":
|
|
||||||
needs_auth = True
|
|
||||||
for path_prefix, policy_name in app_routes.items():
|
for path_prefix, policy_name in app_routes.items():
|
||||||
if policy_name in policies:
|
if get_policy_type(policy_name) not in ("bypass", "deny"):
|
||||||
policy_data = policies[policy_name]
|
needs_auth = True
|
||||||
if policy_data.get("policy_type") != "bypass":
|
|
||||||
needs_auth = True
|
|
||||||
|
|
||||||
if needs_auth:
|
if needs_auth:
|
||||||
for path_prefix, policy_name in app_routes.items():
|
for path_prefix, policy_name in app_routes.items():
|
||||||
if policy_name in auth_policies.get("policies", {}):
|
if get_policy_type(policy_name) == "bypass":
|
||||||
policy_data = auth_policies["policies"][policy_name]
|
lines.append(f" @bypass_{_sanitize_id(path_prefix)} path {path_prefix}*")
|
||||||
if policy_data.get("policy_type") == "bypass":
|
lines.append(f" skip_log @bypass_{_sanitize_id(path_prefix)}")
|
||||||
lines.append(f" @bypass_{_sanitize_id(path_prefix)} path {path_prefix}*")
|
lines.append("")
|
||||||
lines.append(f" skip_log @bypass_{_sanitize_id(path_prefix)}")
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
lines.append(f" forward_auth {AUTHELIA_INTERNAL_URL} {{")
|
lines.append(f" forward_auth {AUTHELIA_INTERNAL_URL} {{")
|
||||||
lines.append(f" uri {AUTHELIA_PORTAL_PATH}/api/authz/forward-auth")
|
lines.append(f" uri {AUTHELIA_PORTAL_PATH}/api/authz/forward-auth")
|
||||||
@@ -155,6 +195,33 @@ def _sanitize_id(value):
|
|||||||
return value.strip("/").replace("/", "_").replace("-", "_")
|
return value.strip("/").replace("/", "_").replace("-", "_")
|
||||||
|
|
||||||
|
|
||||||
|
def _collect_app_domains(apps, server_address):
|
||||||
|
"""Return session cookie entries for all unique app hostnames.
|
||||||
|
|
||||||
|
Authelia v4.37+ requires a session.cookies entry for every domain managed
|
||||||
|
via forward_auth. Without it, Authelia does not recognise the domain and
|
||||||
|
may allow requests through regardless of the access_control policy.
|
||||||
|
"""
|
||||||
|
seen = {server_address}
|
||||||
|
cookies = [
|
||||||
|
{
|
||||||
|
"domain": server_address,
|
||||||
|
"authelia_url": f"https://{server_address}{AUTHELIA_PORTAL_PATH}",
|
||||||
|
"default_redirection_url": f"https://{server_address}",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for app in apps:
|
||||||
|
for host in app.get("hosts", []):
|
||||||
|
if host not in seen:
|
||||||
|
seen.add(host)
|
||||||
|
cookies.append({
|
||||||
|
"domain": host,
|
||||||
|
"authelia_url": f"https://{server_address}{AUTHELIA_PORTAL_PATH}",
|
||||||
|
"default_redirection_url": f"https://{server_address}",
|
||||||
|
})
|
||||||
|
return cookies
|
||||||
|
|
||||||
|
|
||||||
def build_authelia_config(auth_policies, routes, apps):
|
def build_authelia_config(auth_policies, routes, apps):
|
||||||
server_address = os.environ.get("SERVER_ADDRESS", "localhost")
|
server_address = os.environ.get("SERVER_ADDRESS", "localhost")
|
||||||
|
|
||||||
@@ -181,13 +248,7 @@ def build_authelia_config(auth_policies, routes, apps):
|
|||||||
},
|
},
|
||||||
"session": {
|
"session": {
|
||||||
"secret": session_secret,
|
"secret": session_secret,
|
||||||
"cookies": [
|
"cookies": _collect_app_domains(apps, server_address),
|
||||||
{
|
|
||||||
"domain": server_address,
|
|
||||||
"authelia_url": f"https://{server_address}{AUTHELIA_PORTAL_PATH}",
|
|
||||||
"default_redirection_url": f"https://{server_address}",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"encryption_key": storage_encryption_key,
|
"encryption_key": storage_encryption_key,
|
||||||
|
|||||||
Reference in New Issue
Block a user