Skip to content

Commit 6167765

Browse files
committed
[Feature] P2S VPNGateway support for flexnode
1 parent a68b8d0 commit 6167765

File tree

14 files changed

+2302
-42
lines changed

14 files changed

+2302
-42
lines changed

aks-flex-node-sudoers

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl status node-problem-det
3838
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl check kubelet
3939
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl check containerd
4040
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl check node-problem-detector
41+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl enable openvpn@*
42+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl start openvpn@*
43+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl stop openvpn@*
44+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl restart openvpn@*
45+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl status openvpn@*
4146
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl is-active *
4247
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl is-enabled *
4348
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/systemctl list-unit-files *
@@ -82,10 +87,11 @@ aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/apt -y remove *
8287
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/dpkg -i *
8388
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/dpkg --purge *
8489
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/lsof *
90+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/apt install -y openvpn
8591

8692
# Directory and file operations for Kubernetes paths - simplified for compatibility
8793
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/mkdir *, /usr/bin/mkdir *
88-
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/mkdir -p /etc/kubernetes/*, /bin/mkdir -p /var/lib/kubelet/*, /bin/mkdir -p /var/lib/cni/*, /bin/mkdir -p /etc/containerd/*, /bin/mkdir -p /opt/cni/bin, /bin/mkdir -p /etc/cni/net.d, /bin/mkdir -p /etc/systemd/system/kubelet.service.d, /bin/mkdir -p /etc/sysctl.d, /bin/mkdir -p /etc/modules-load.d
94+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/mkdir -p /etc/kubernetes/*, /bin/mkdir -p /var/lib/kubelet/*, /bin/mkdir -p /var/lib/cni/*, /bin/mkdir -p /etc/containerd/*, /bin/mkdir -p /opt/cni/bin, /bin/mkdir -p /etc/cni/net.d, /bin/mkdir -p /etc/systemd/system/kubelet.service.d, /bin/mkdir -p /etc/sysctl.d, /bin/mkdir -p /etc/modules-load.d, /bin/mkdir -p /etc/aks-flex-node/*, /bin/mkdir -p /etc/openvpn
8995
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/cp *, /bin/mv *, /bin/rm *
9096
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/chmod *, /bin/chown *
9197
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/ln *, /usr/bin/ln *
@@ -94,6 +100,7 @@ aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/curl *, /usr/bin/wget *
94100
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/tar *, /usr/bin/unzip *
95101
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/ls *, /usr/bin/ls *
96102
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/bin/test *, /bin/test *
103+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/cat *, /usr/bin/cat *
97104

98105
# System configuration for Kubernetes
99106
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/sysctl --system
@@ -116,9 +123,15 @@ aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/cat /etc/kubernetes/*
116123
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/cat /var/lib/kubelet/kubeconfig
117124

118125

119-
# Network operations for troubleshooting
126+
# Network operations for troubleshooting and VPN gateway management
120127
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip route
121128
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip addr
129+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip route add *
130+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip route del *
131+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip route delete *
132+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/ip route show *
133+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /usr/sbin/iptables *
134+
aks-flex-node ALL=(root) NOPASSWD:SETENV: /sbin/iptables *
122135
aks-flex-node ALL=(root) NOPASSWD:SETENV: /bin/netstat -rn
123136

124137
# Read-only Kubernetes API check for node readiness (used by status collector)

assets/img/README/image.png

194 KB
Loading

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ require (
2020

2121
require (
2222
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
23+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 // indirect
24+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 // indirect
25+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 // indirect
2326
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
2427
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
2528
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDo
88
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
99
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 h1:qiir/pptnHqp6hV8QwV+IExYIf6cPsXBfUDUXQ27t2Y=
1010
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2/go.mod h1:jVRrRDLCOuif95HDYC23ADTMlvahB7tMdl519m9Iyjc=
11+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 h1:figxyQZXzZQIcP3njhC68bYUiTw45J8/SsHaLW8Ax0M=
12+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0/go.mod h1:TmlMW4W5OvXOmOyKNnor8nlMMiO1ctIyzmHme/VHsrA=
1113
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v5 v5.0.0 h1:5n7dPVqsWfVKw+ZiEKSd3Kzu7gwBkbEBkeXb8rgaE9Q=
1214
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v5 v5.0.0/go.mod h1:HcZY0PHPo/7d75p99lB6lK0qYOP4vLRJUBpiehYXtLQ=
1315
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/hybridcompute/armhybridcompute v1.2.0 h1:7UuAn4ljE+H3GQ7qts3c7oAaMRvge68EgyckoNP/1Ro=
1416
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/hybridcompute/armhybridcompute v1.2.0/go.mod h1:F2eDq/BGK2LOEoDtoHbBOphaPqcjT0K/Y5Am8vf7+0w=
1517
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
1618
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI=
19+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA=
20+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0=
21+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
22+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
1723
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=
1824
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw=
1925
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=

pkg/bootstrapper/bootstrapper.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"go.goms.io/aks/AKSFlexNode/pkg/components/runc"
1515
"go.goms.io/aks/AKSFlexNode/pkg/components/services"
1616
"go.goms.io/aks/AKSFlexNode/pkg/components/system_configuration"
17+
"go.goms.io/aks/AKSFlexNode/pkg/components/vpn_gateway"
1718
"go.goms.io/aks/AKSFlexNode/pkg/config"
1819
)
1920

@@ -34,6 +35,7 @@ func (b *Bootstrapper) Bootstrap(ctx context.Context) (*ExecutionResult, error)
3435
// Define the bootstrap steps in order - using modules directly
3536
steps := []Executor{
3637
arc.NewInstaller(b.logger), // Setup Arc
38+
vpn_gateway.NewInstaller(b.logger), // Setup VPN Gateway (if enabled)
3739
services.NewUnInstaller(b.logger), // Stop kubelet before setup
3840
system_configuration.NewInstaller(b.logger), // Configure system (early)
3941
runc.NewInstaller(b.logger), // Install runc
@@ -59,6 +61,7 @@ func (b *Bootstrapper) Unbootstrap(ctx context.Context) (*ExecutionResult, error
5961
containerd.NewUnInstaller(b.logger), // Uninstall containerd binary
6062
runc.NewUnInstaller(b.logger), // Uninstall runc binary
6163
system_configuration.NewUnInstaller(b.logger), // Clean system settings
64+
vpn_gateway.NewUnInstaller(b.logger), // Clean VPN Gateway
6265
arc.NewUnInstaller(b.logger), // Uninstall Arc (after cleanup)
6366
}
6467

pkg/components/cni/cni_setup_installer.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,6 @@ func (i *Installer) IsCompleted(ctx context.Context) bool {
8989
}
9090
}
9191

92-
// Validate Step 3: Bridge configuration
93-
configPath := filepath.Join(DefaultCNIConfDir, bridgeConfigFile)
94-
if !utils.FileExistsAndValid(configPath) {
95-
i.logger.Debug("Bridge configuration file not found")
96-
return false
97-
}
98-
9992
i.logger.Debug("CNI setup validation passed - all components properly configured")
10093
return true
10194
}

pkg/components/kubelet/kubelet_installer.go

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -208,42 +208,58 @@ func (i *Installer) createKubeletDefaultsFile() error {
208208
labels = append(labels, fmt.Sprintf("%s=%s", key, value))
209209
}
210210

211+
// Build kubelet flags dynamically
212+
kubeletFlags := []string{
213+
fmt.Sprintf("--v=%d", i.config.Node.Kubelet.Verbosity),
214+
"--address=0.0.0.0",
215+
"--anonymous-auth=false",
216+
"--authentication-token-webhook=true",
217+
"--authorization-mode=Webhook",
218+
"--cgroup-driver=systemd",
219+
"--cgroups-per-qos=true",
220+
"--enforce-node-allocatable=pods",
221+
fmt.Sprintf("--cluster-dns=%s", i.config.Node.Kubelet.DNSServiceIP),
222+
"--cluster-domain=cluster.local",
223+
"--event-qps=0",
224+
fmt.Sprintf("--eviction-hard=%s", mapToEvictionThresholds(i.config.Node.Kubelet.EvictionHard, ",")),
225+
fmt.Sprintf("--kube-reserved=%s", mapToKeyValuePairs(i.config.Node.Kubelet.KubeReserved, ",")),
226+
fmt.Sprintf("--image-gc-high-threshold=%d", i.config.Node.Kubelet.ImageGCHighThreshold),
227+
fmt.Sprintf("--image-gc-low-threshold=%d", i.config.Node.Kubelet.ImageGCLowThreshold),
228+
fmt.Sprintf("--max-pods=%d", i.config.Node.MaxPods),
229+
"--node-status-update-frequency=10s",
230+
fmt.Sprintf("--pod-infra-container-image=%s", i.config.Containerd.PauseImage),
231+
"--pod-max-pids=-1",
232+
"--protect-kernel-defaults=true",
233+
"--read-only-port=0",
234+
"--resolv-conf=/run/systemd/resolve/resolv.conf",
235+
"--streaming-connection-idle-timeout=4h",
236+
"--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256",
237+
}
238+
239+
// Add VPN node IP if VPN gateway is enabled and connected
240+
if vpnIP := i.getVPNInterfaceIP(); vpnIP != "" {
241+
kubeletFlags = append(kubeletFlags, fmt.Sprintf("--node-ip=%s", vpnIP))
242+
i.logger.Infof("Configuring kubelet to use VPN interface IP: %s", vpnIP)
243+
}
244+
245+
// Format flags with proper line continuation
246+
flagsFormatted := make([]string, len(kubeletFlags))
247+
for i, flag := range kubeletFlags {
248+
flagsFormatted[i] = fmt.Sprintf(" %s \\", flag)
249+
}
250+
// Remove trailing backslash from last flag
251+
if len(flagsFormatted) > 0 {
252+
lastFlag := flagsFormatted[len(flagsFormatted)-1]
253+
flagsFormatted[len(flagsFormatted)-1] = strings.TrimSuffix(lastFlag, " \\")
254+
}
255+
211256
kubeletDefaults := fmt.Sprintf(`KUBELET_NODE_LABELS="%s"
212257
KUBELET_CONFIG_FILE_FLAGS=""
213258
KUBELET_FLAGS="\
214-
--v=%d \
215-
--address=0.0.0.0 \
216-
--anonymous-auth=false \
217-
--authentication-token-webhook=true \
218-
--authorization-mode=Webhook \
219-
--cgroup-driver=systemd \
220-
--cgroups-per-qos=true \
221-
--enforce-node-allocatable=pods \
222-
--cluster-dns=%s \
223-
--cluster-domain=cluster.local \
224-
--event-qps=0 \
225-
--eviction-hard=%s \
226-
--kube-reserved=%s \
227-
--image-gc-high-threshold=%d \
228-
--image-gc-low-threshold=%d \
229-
--max-pods=%d \
230-
--node-status-update-frequency=10s \
231-
--pod-max-pids=-1 \
232-
--protect-kernel-defaults=true \
233-
--read-only-port=0 \
234-
--resolv-conf=/run/systemd/resolve/resolv.conf \
235-
--streaming-connection-idle-timeout=4h \
236-
--rotate-certificates=true \
237-
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256 \
259+
%s \
238260
"`,
239261
strings.Join(labels, ","),
240-
i.config.Node.Kubelet.Verbosity,
241-
i.config.Node.Kubelet.DNSServiceIP,
242-
mapToEvictionThresholds(i.config.Node.Kubelet.EvictionHard, ","),
243-
mapToKeyValuePairs(i.config.Node.Kubelet.KubeReserved, ","),
244-
i.config.Node.Kubelet.ImageGCHighThreshold,
245-
i.config.Node.Kubelet.ImageGCLowThreshold,
246-
i.config.Node.MaxPods)
262+
strings.Join(flagsFormatted, "\n"))
247263

248264
// Ensure /etc/default directory exists
249265
if err := utils.RunSystemCommand("mkdir", "-p", etcDefaultDir); err != nil {
@@ -709,3 +725,28 @@ func mapToEvictionThresholds(m map[string]string, separator string) string {
709725
}
710726
return strings.Join(pairs, separator)
711727
}
728+
729+
// getVPNInterfaceIP returns the IP address of the VPN interface if VPN is enabled and connected
730+
func (i *Installer) getVPNInterfaceIP() string {
731+
// Check if VPN gateway is enabled in configuration
732+
if !i.config.IsVPNGatewayEnabled() {
733+
return ""
734+
}
735+
736+
// Get VPN interface using the generic utility function
737+
vpnInterface, err := utils.GetVPNInterface()
738+
if err != nil {
739+
i.logger.Debugf("VPN interface not found: %v", err)
740+
return ""
741+
}
742+
743+
// Get IP address of the VPN interface
744+
ip, err := utils.GetVPNInterfaceIP(vpnInterface)
745+
if err != nil {
746+
i.logger.Debugf("Failed to get VPN interface IP: %v", err)
747+
return ""
748+
}
749+
750+
i.logger.Infof("Found VPN interface %s with IP: %s", vpnInterface, ip)
751+
return ip
752+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# VPN Gateway Component
2+
3+
This component provides VPN connectivity for AKS Flex Node using OpenVPN over Point-to-Site (P2S) connections. It's designed for scenarios where a limited number of clients need secure access to a virtual network.
4+
5+
![VPN Gateway Architecture](../../../assets/img/README/image.png)
6+
7+
## Overview
8+
9+
The VPN Gateway component enables secure connectivity between AKS Flex Nodes and Azure Virtual Networks through:
10+
11+
- **Certificate-based authentication** using self-generated root and client certificates
12+
- **OpenVPN SSL tunnel** for encrypted communication
13+
- **Automatic IP management** to update node IPs when VPN interface changes
14+
- **Azure integration** for seamless VPN gateway configuration
15+
16+
## Steps
17+
1. Prepare Azure Resources
18+
- Create a GatewaySubnet within the AKS VNet
19+
- Deploy a Route-based Azure VPN Gateway into the GatewaySubnet
20+
21+
2. Prepare Certificates
22+
- root certificate: will be uploaded to Azure as a "trusted" cert (a Base64 encoded X.509 .cer file.)
23+
- client certificates: generated from the root certificate and to be installed on each client computer for client authentication
24+
25+
3. Configure VPN client profile
26+
27+
## References
28+
29+
[Configure server settings for P2S VPN Gateway certificate authentication](https://learn.microsoft.com/en-us/azure/vpn-gateway/point-to-site-certificate-gateway)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package vpn_gateway
2+
3+
import (
4+
"path/filepath"
5+
"time"
6+
)
7+
8+
const (
9+
// VPN Gateway default name
10+
defaultVPNGatewayName = "vpn-gateway"
11+
12+
// Azure VPN Gateway configuration
13+
vpnClientRootCertName = "VPNClientRootCert"
14+
gatewaySubnetName = "GatewaySubnet"
15+
gatewaySubnetPrefix = 27 // /27 subnet for GatewaySubnet
16+
17+
// Directory paths
18+
systemConfigDir = "/etc/aks-flex-node"
19+
certificatesDir = "/etc/aks-flex-node/certs"
20+
openVPNConfigDir = "/etc/openvpn"
21+
22+
// File names
23+
vpnConfigFileName = "vpn-config.ovpn"
24+
vpnClientCertFileName = "vpn-client.crt"
25+
vpnClientKeyFileName = "vpn-client.key"
26+
vpnRootCertFileName = "vpn-root-ca.crt"
27+
openVPNConfigFileName = "vpnconfig.conf"
28+
29+
// File permissions
30+
certificatesDirPerm = 0700
31+
configDirPerm = 0755
32+
privateKeyFilePerm = 0600
33+
certificateFilePerm = 0644
34+
35+
// Certificate configuration
36+
certificateKeySize = 2048
37+
certificateValidYears = 10
38+
certificateCommonName = "VPN CA"
39+
40+
// PEM block types
41+
rsaPrivateKeyType = "RSA PRIVATE KEY"
42+
certificateType = "CERTIFICATE"
43+
44+
// Timeouts and intervals
45+
gatewayProvisioningTimeout = 30 * time.Minute // VPN Gateway provisioning timeout
46+
gatewayStatusCheckInterval = 30 * time.Second // Polling interval for gateway status
47+
vpnConnectionTimeout = 1 * time.Minute // VPN connection establishment timeout
48+
vpnConnectionCheckInterval = 2 * time.Second // Interval for VPN connection checks
49+
50+
// System paths for validation
51+
systemEtcPrefix = "/etc/"
52+
systemUsrPrefix = "/usr/"
53+
systemVarPrefix = "/var/"
54+
55+
// Temporary file patterns
56+
tempVPNConfigPattern = "vpnconfig-*.ovpn"
57+
tempVPNCertPattern = "vpn-cert-*.tmp"
58+
tempVPNZipPattern = "vpnconfig-*.zip"
59+
tempVPNExtractPrefix = "vpnconfig-"
60+
61+
// OpenVPN configuration paths in extracted ZIP
62+
openVPNConfigPath = "OpenVPN/vpnconfig.ovpn"
63+
genericVPNConfigPath = "Generic/VpnSettings.xml"
64+
65+
// OpenVPN service template
66+
openVPNServiceTemplate = "openvpn@vpnconfig"
67+
openVPNServiceName = "vpnconfig"
68+
69+
// Public IP naming pattern
70+
gatewayPublicIPName = "vpn-gateway-ip"
71+
vpnGatewayName = "vpn-gateway"
72+
73+
// Point-to-Site configuration name
74+
p2sConfigName = "P2SConfig"
75+
)
76+
77+
// GetVPNClientCertPath returns the full path to the VPN client certificate file
78+
func GetVPNClientCertPath() string {
79+
return filepath.Join(certificatesDir, vpnClientCertFileName)
80+
}
81+
82+
// GetVPNClientKeyPath returns the full path to the VPN client private key file
83+
func GetVPNClientKeyPath() string {
84+
return filepath.Join(certificatesDir, vpnClientKeyFileName)
85+
}
86+
87+
// GetVPNRootCertPath returns the full path to the VPN root CA certificate file
88+
func GetVPNRootCertPath() string {
89+
return filepath.Join(certificatesDir, vpnRootCertFileName)
90+
}
91+
92+
// GetOpenVPNConfigPath returns the full path to the OpenVPN configuration file
93+
func GetOpenVPNConfigPath() string {
94+
return filepath.Join(openVPNConfigDir, openVPNConfigFileName)
95+
}
96+
97+
// GetVPNConfigPath returns the full path to the VPN configuration file in system config directory
98+
func GetVPNConfigPath() string {
99+
return filepath.Join(systemConfigDir, vpnConfigFileName)
100+
}

0 commit comments

Comments
 (0)