openvpn-endpoint-server/provisioning-tool/config_generator.py

207 lines
4.7 KiB
Python

"""Configuration generator for mGuard routers."""
from dataclasses import dataclass
from typing import Optional
import json
@dataclass
class GatewayConfig:
"""Gateway configuration data."""
name: str
vpn_server: str
vpn_port: int
ca_cert: str
client_cert: str
client_key: str
ta_key: Optional[str] = None
class ConfigGenerator:
"""Generate configuration files for mGuard routers."""
@staticmethod
def generate_openvpn_config(config: GatewayConfig) -> str:
"""Generate OpenVPN client configuration.
Args:
config: Gateway configuration data
Returns:
OpenVPN config file content
"""
ovpn = f"""# OpenVPN Client Configuration
# Generated for: {config.name}
client
dev tun
proto udp
remote {config.vpn_server} {config.vpn_port}
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3
<ca>
{config.ca_cert}
</ca>
<cert>
{config.client_cert}
</cert>
<key>
{config.client_key}
</key>
"""
if config.ta_key:
ovpn += f"""
<tls-auth>
{config.ta_key}
</tls-auth>
key-direction 1
"""
return ovpn
@staticmethod
def generate_atv_vpn_section(config: GatewayConfig) -> str:
"""Generate ATV configuration section for VPN.
Note: This is a simplified version. Real ATV files have
a more complex structure that should be merged with existing config.
Args:
config: Gateway configuration data
Returns:
ATV config section
"""
# ATV is essentially a key-value format
# This is a simplified representation
atv_section = f"""
[vpn_client_1]
enabled = 1
name = {config.name}
type = openvpn
remote = {config.vpn_server}
port = {config.vpn_port}
protocol = udp
cipher = AES-256-GCM
"""
return atv_section
@staticmethod
def generate_mguard_script(
gateway_name: str,
endpoints: list[dict]
) -> str:
"""Generate mGuard CLI script for firewall configuration.
Args:
gateway_name: Name of the gateway
endpoints: List of endpoint configurations
Returns:
Shell script for mGuard CLI
"""
script = f"""#!/bin/bash
# Firewall configuration script for {gateway_name}
# Run this on the mGuard via SSH
MBIN="/Packages/mguard-api_0/mbin"
echo "Configuring firewall rules for {gateway_name}..."
"""
for i, ep in enumerate(endpoints):
rule_name = f"endpoint_{i}_{ep['name'].replace(' ', '_')}"
script += f"""
# Rule for {ep['name']}
$MBIN/action fwrules/add \\
--name "{rule_name}" \\
--source "any" \\
--destination "{ep['internal_ip']}" \\
--port "{ep['port']}" \\
--protocol "{ep['protocol']}" \\
--action "accept"
"""
script += """
echo "Firewall rules configured."
$MBIN/action config/save
echo "Configuration saved."
"""
return script
def create_provisioning_package(
gateway_name: str,
vpn_server: str,
vpn_port: int,
ca_cert: str,
client_cert: str,
client_key: str,
endpoints: list[dict],
output_dir: str = "."
) -> dict:
"""Create a complete provisioning package.
Args:
gateway_name: Name of the gateway
vpn_server: VPN server address
vpn_port: VPN server port
ca_cert: CA certificate content
client_cert: Client certificate content
client_key: Client private key content
endpoints: List of endpoint configurations
output_dir: Output directory for files
Returns:
Dictionary with file paths
"""
from pathlib import Path
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
config = GatewayConfig(
name=gateway_name,
vpn_server=vpn_server,
vpn_port=vpn_port,
ca_cert=ca_cert,
client_cert=client_cert,
client_key=client_key
)
# Generate OpenVPN config
ovpn_content = ConfigGenerator.generate_openvpn_config(config)
ovpn_file = output_path / f"{gateway_name}.ovpn"
ovpn_file.write_text(ovpn_content)
# Generate firewall script
fw_script = ConfigGenerator.generate_mguard_script(gateway_name, endpoints)
fw_file = output_path / f"{gateway_name}_firewall.sh"
fw_file.write_text(fw_script)
# Generate info JSON
info = {
"gateway_name": gateway_name,
"vpn_server": vpn_server,
"vpn_port": vpn_port,
"endpoints": endpoints
}
info_file = output_path / f"{gateway_name}_info.json"
info_file.write_text(json.dumps(info, indent=2))
return {
"ovpn": str(ovpn_file),
"firewall_script": str(fw_file),
"info": str(info_file)
}