feat(check,serve): Startvalidierung, HTTPS-Server, Signal-Handling und Versionscheck
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBHF4R9EAejDJUMdwr6C68
This commit is contained in:
parent
7e23df9fec
commit
2d223c5823
9 changed files with 1158 additions and 6 deletions
94
cmd/vpnportal/uidemo_test.go
Normal file
94
cmd/vpnportal/uidemo_test.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//go:build uidemo
|
||||
|
||||
// Dieser Test startet das Portal mit Attrappen für AD und Firewall auf
|
||||
// http://127.0.0.1:8080, damit die Oberfläche ohne echte Backends begutachtet
|
||||
// werden kann. Aufruf:
|
||||
//
|
||||
// go test -tags uidemo ./cmd/vpnportal/ -run TestUIDemo -v -timeout 0
|
||||
//
|
||||
// Anmeldung mit beliebigem Benutzernamen und Passwort.
|
||||
// Browser erlauben Secure-Cookies auf 127.0.0.1, deshalb funktioniert der
|
||||
// gesamte Ablauf auch ohne TLS.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.ravensburg.dev/cabele/opnsense-portal/internal/audit"
|
||||
"git.ravensburg.dev/cabele/opnsense-portal/internal/auth"
|
||||
"git.ravensburg.dev/cabele/opnsense-portal/internal/web"
|
||||
)
|
||||
|
||||
type demoAuth struct{}
|
||||
|
||||
func (demoAuth) Authenticate(ctx context.Context, u, p string) (*auth.Identity, error) {
|
||||
return &auth.Identity{Username: "mmueller", Groups: []string{"VPN-Users"}}, nil
|
||||
}
|
||||
|
||||
type demoCerts struct{}
|
||||
|
||||
func (demoCerts) EntriesFor(ctx context.Context, user string) ([]web.CertEntry, error) {
|
||||
return []web.CertEntry{
|
||||
{Token: "1:a1", InstanceName: "VPN Homeoffice", CommonName: "mmueller",
|
||||
ValidTo: time.Now().AddDate(1, 2, 0)},
|
||||
{Token: "2:b1", InstanceName: "VPN Außendienst", CommonName: "mmueller",
|
||||
ValidTo: time.Now().AddDate(0, 0, 12)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (demoCerts) Export(ctx context.Context, user, vpnID, refID, format string) (*web.ExportStream, error) {
|
||||
return &web.ExportStream{
|
||||
Filename: "vpn-demo-mmueller.ovpn",
|
||||
ContentType: "application/x-openvpn-profile",
|
||||
Body: io.NopCloser(strings.NewReader("client\nremote fw01.testfirma.local 1194\n")),
|
||||
InstanceName: "VPN Homeoffice",
|
||||
CommonName: "mmueller",
|
||||
ValidTo: time.Now().AddDate(1, 0, 0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (demoCerts) Pattern(user string) string { return user }
|
||||
|
||||
// leereCerts zeigt den Zustand "kein Zertifikat hinterlegt".
|
||||
type leereCerts struct{ demoCerts }
|
||||
|
||||
func (leereCerts) EntriesFor(ctx context.Context, user string) ([]web.CertEntry, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type demoAudit struct{ t *testing.T }
|
||||
|
||||
func (d demoAudit) Log(e audit.Event) { d.t.Logf("audit: %+v", e) }
|
||||
|
||||
func TestUIDemo(t *testing.T) {
|
||||
rn, err := web.NewRenderer(web.Brand{Title: "VPN-Portal Testfirma", Version: "uidemo"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Mit VPNPORTAL_UIDEMO_EMPTY=1 den Zustand "kein Zertifikat" begutachten.
|
||||
var certs web.CertSource = demoCerts{}
|
||||
if os.Getenv("VPNPORTAL_UIDEMO_EMPTY") != "" {
|
||||
certs = leereCerts{}
|
||||
}
|
||||
srv, err := web.NewServer(web.Deps{
|
||||
Auth: demoAuth{}, Certs: certs, Audit: demoAudit{t},
|
||||
Sessions: web.NewSessionStore(30*time.Minute, nil),
|
||||
Limiter: web.NewLimiter(nil), Renderer: rn,
|
||||
SupportContact: "it-helpdesk@testfirma.de",
|
||||
SessionTTL: 30 * time.Minute,
|
||||
MinLoginDuration: time.Millisecond,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("Oberfläche unter http://127.0.0.1:8080 — mit Strg-C beenden")
|
||||
if err := http.ListenAndServe("127.0.0.1:8080", srv.Handler()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue