add export configuration feature for Caddy

This commit is contained in:
Eduardo Silva
2026-03-14 11:54:49 -03:00
parent d686e6831d
commit ac87874b8a
4 changed files with 182 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
import json
import os
from app_gateway.models import (
AccessPolicy, Application, ApplicationPolicy
)
from gatekeeper.models import (
AuthMethod, GatekeeperGroup, GatekeeperIPAddress, GatekeeperUser
)
RESERVED_APP_NAME = 'wireguard_webadmin'
POLICY_TYPE_MAP = {
'public': 'bypass',
'protected': 'protected',
'deny': 'deny',
}
def build_applications_data():
applications = Application.objects.exclude(name=RESERVED_APP_NAME).prefetch_related('hosts')
entries = []
for app in applications:
entry = {
'id': app.name,
'name': app.display_name or app.name,
'hosts': list(app.hosts.values_list('hostname', flat=True)),
'upstream': app.upstream,
}
entries.append(entry)
return {'entries': entries}
def _build_auth_method_entry(method):
entry = {'type': method.auth_type}
if method.auth_type == 'totp':
entry['totp_secret'] = method.totp_secret
entry['totp_before_auth'] = method.totp_before_auth
elif method.auth_type == 'oidc':
entry['provider'] = method.oidc_provider
entry['client_id'] = method.oidc_client_id
entry['client_secret'] = method.oidc_client_secret
entry['allowed_domains'] = list(
method.allowed_domains.values_list('domain', flat=True)
)
entry['allowed_emails'] = list(
method.allowed_emails.values_list('email', flat=True)
)
elif method.auth_type == 'ip_address':
rules = []
for ip_entry in GatekeeperIPAddress.objects.filter(auth_method=method):
rules.append({
'address': str(ip_entry.address),
'prefix_length': ip_entry.prefix_length,
'action': ip_entry.action,
'description': ip_entry.description,
})
entry['rules'] = rules
return entry
def build_auth_policies_data():
auth_methods = {}
for method in AuthMethod.objects.all():
auth_methods[method.name] = _build_auth_method_entry(method)
groups = {}
for group in GatekeeperGroup.objects.prefetch_related('users'):
groups[group.name] = {
'users': list(group.users.values_list('username', flat=True)),
}
users = {}
for user in GatekeeperUser.objects.all():
users[user.username] = {
'email': user.email,
'password_hash': user.password_hash or '',
'totp_secret': user.totp_secret,
}
policies = {}
for policy in AccessPolicy.objects.prefetch_related('groups', 'methods'):
policies[policy.name] = {
'policy_type': POLICY_TYPE_MAP.get(policy.policy_type, policy.policy_type),
'groups': list(policy.groups.values_list('name', flat=True)),
'methods': list(policy.methods.values_list('name', flat=True)),
}
return {
'auth_methods': auth_methods,
'groups': groups,
'users': users,
'policies': policies,
}
def build_routes_data():
applications = (
Application.objects
.exclude(name=RESERVED_APP_NAME)
.prefetch_related('routes__policy')
)
entries = {}
for app in applications:
try:
app_policy = ApplicationPolicy.objects.get(application=app)
default_policy = app_policy.default_policy.name
except ApplicationPolicy.DoesNotExist:
default_policy = None
routes = []
for route in app.routes.all().order_by('order', 'path_prefix'):
routes.append({
'id': route.name,
'path_prefix': route.path_prefix,
'policy': route.policy.name,
})
entry = {'routes': routes}
if default_policy:
entry['default_policy'] = default_policy
entries[app.name] = entry
return {'entries': entries}
def export_caddy_config(output_dir):
os.makedirs(output_dir, exist_ok=True)
file_map = {
'applications.json': build_applications_data,
'auth_policies.json': build_auth_policies_data,
'routes.json': build_routes_data,
}
for filename, builder in file_map.items():
filepath = os.path.join(output_dir, filename)
with open(filepath, 'w', encoding='utf-8') as output_file:
json.dump(builder(), output_file, indent=2)
output_file.write('\n')