Show OpenVPN OIDC prerequisites and exposed management port
This commit is contained in:
1 parent
64f1d89a2f
commit
ea9c885a15
10 files changed
+90
-5
No files matched your search
@@ -285,6 +285,7 @@ func (s *Server) RegisterRoutes(r *gin.Engine) {
|
||||
ops.POST("/binaries/install/:name", s.installBinary)
|
||||
ops.GET("/binaries/install-hint/:name", s.binaryInstallHint)
|
||||
ops.PUT("/tunnels/:id/policy", s.saveTrafficPolicy)
|
||||
ops.GET("/tunnels/openvpn/oidc-readiness", s.openvpnOIDCReadiness)
|
||||
|
||||
// 批量操作 & 任务管理
|
||||
ops.POST("/tunnels/batch/start", s.batchTunnels(taskmgr.ActionStart))
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"vpn-platform/backend/internal/nginxgateway"
|
||||
"vpn-platform/backend/internal/service"
|
||||
"vpn-platform/backend/internal/tlsservice"
|
||||
)
|
||||
|
||||
var oidcVersionPattern = regexp.MustCompile(`(?m)^version: ([0-9][0-9A-Za-z.+-]{1,32})\s*$`)
|
||||
|
||||
// This checks local prerequisites only. It never tests credentials or claims
|
||||
// that an OIDC issuer, callback domain or user authorization is configured.
|
||||
func (s *Server) openvpnOIDCReadiness(c *gin.Context) {
|
||||
path := filepath.Join(service.BaseDir(), "bin", "openvpn-auth-oauth2")
|
||||
info, err := os.Stat(path)
|
||||
if err != nil || !info.Mode().IsRegular() || info.Mode()&0o111 == 0 {
|
||||
path, _ = service.LookBin("openvpn-auth-oauth2")
|
||||
}
|
||||
version := ""
|
||||
if path != "" {
|
||||
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
|
||||
defer cancel()
|
||||
if output, err := exec.CommandContext(ctx, path, "--version").Output(); err == nil {
|
||||
if match := oidcVersionPattern.FindSubmatch(output); len(match) == 2 {
|
||||
version = strings.TrimSpace(string(match[1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
tls := tlsservice.Status()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"component_installed": path != "", "component_version": version,
|
||||
"https_management_ready": tls.Mode == "nginx" && tls.Valid && nginxgateway.Stage() == "https",
|
||||
"management_domain": tls.Domain,
|
||||
"authentication_entry_ready": false, // Depends on a distinct callback site and a configured provider.
|
||||
})
|
||||
}
|
||||
@@ -51,6 +51,7 @@ type CertificateStatus struct {
|
||||
NotBefore time.Time `json:"not_before,omitempty"`
|
||||
NotAfter time.Time `json:"not_after,omitempty"`
|
||||
Renewal string `json:"renewal_mode"`
|
||||
DirectPortPublic bool `json:"management_direct_public"`
|
||||
}
|
||||
|
||||
func ValidDomain(domain string) bool {
|
||||
@@ -222,6 +223,15 @@ func Status() CertificateStatus {
|
||||
config := state.config
|
||||
state.RUnlock()
|
||||
status := CertificateStatus{Enabled: config.domain != "" && config.mode == "autocert", Domain: config.domain, Mode: config.mode, DNS: []string{}, HTTPAddr: config.httpAddr, HTTPSAddr: config.httpsAddr, Renewal: config.mode}
|
||||
if config.mode == "nginx" {
|
||||
listenAddress := os.Getenv("VPN_LISTEN_ADDR")
|
||||
if listenAddress == "" {
|
||||
listenAddress = ":18080"
|
||||
}
|
||||
if host, _, err := net.SplitHostPort(listenAddress); err == nil {
|
||||
status.DirectPortPublic = host == "" || host == "0.0.0.0" || host == "::"
|
||||
}
|
||||
}
|
||||
if desired, err := configFromEnvironment(config.dataDir); err == nil {
|
||||
status.ConfiguredDomain = desired.domain
|
||||
status.ConfiguredMode = desired.mode
|
||||
@@ -233,7 +243,9 @@ func Status() CertificateStatus {
|
||||
status.Domain = ""
|
||||
if config.domain != "" {
|
||||
readCertificate(filepath.Join("/etc/letsencrypt/live", config.domain, "fullchain.pem"), config.domain, &status)
|
||||
if status.Valid { status.Domain = config.domain }
|
||||
if status.Valid {
|
||||
status.Domain = config.domain
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
@@ -80,7 +80,11 @@ func TestNginxModeDoesNotBindGoListeners(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
status := Status()
|
||||
if status.Mode != "nginx" || status.Enabled || status.Domain != "" || status.ConfiguredDomain != "test-link.appx365.com" {
|
||||
if status.Mode != "nginx" || status.Enabled || status.Domain != "" || status.ConfiguredDomain != "test-link.appx365.com" || !status.DirectPortPublic {
|
||||
t.Fatalf("proxy mode must not claim Go listens: %+v", status)
|
||||
}
|
||||
t.Setenv("VPN_LISTEN_ADDR", "127.0.0.1:18080")
|
||||
if Status().DirectPortPublic {
|
||||
t.Fatal("loopback management listener must not be marked public")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user