package api import ( "context" "net/http" "os" "os/exec" "path/filepath" "regexp" "strings" "time" "github.com/gin-gonic/gin" "vpn-platform/backend/internal/identityprovider" "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() builtInIssuer, builtInClientID, builtInEnabled := identityprovider.PublicClient() port, _ := authGatewayPort(tls.Domain) issuerRoute, callbackRoute := nginxgateway.AuthRouteReady(port) 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": port > 0 && callbackRoute, "built_in_issuer": builtInIssuer, "built_in_client_id": builtInClientID, "built_in_enabled": builtInEnabled, "built_in_gateway_ready": issuerRoute, }) }