Fix review findings for embedded VNC server

This commit is contained in:
Viktor Liu
2026-06-10 10:57:50 +02:00
parent 2fdc3aea4c
commit f2c79201b3
39 changed files with 694 additions and 289 deletions
+60 -7
View File
@@ -4,7 +4,10 @@ package main
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"strings"
"time"
@@ -17,6 +20,18 @@ import (
"github.com/netbirdio/netbird/client/proto"
)
// Approval metadata that is remote-peer or dashboard controlled is passed to
// the forked netbird-ui via environment variables rather than argv, so it is
// not exposed to other local users through ps.
const (
envApprovalInitiator = "NB_APPROVAL_INITIATOR"
envApprovalPeerName = "NB_APPROVAL_PEER_NAME"
envApprovalSourceIP = "NB_APPROVAL_SOURCE_IP"
envApprovalUsername = "NB_APPROVAL_USERNAME"
envApprovalKeyFingerprint = "NB_APPROVAL_KEY_FINGERPRINT"
envApprovalSubject = "NB_APPROVAL_SUBJECT"
)
// handleApprovalEvent forks a netbird-ui child process to render the
// dialog on its own fyne main loop. Top-level windows opened from a
// background goroutine of the tray process don't render reliably on
@@ -31,18 +46,56 @@ func (s *serviceClient) handleApprovalEvent(ev *proto.SystemEvent) {
log.Warnf("approval event missing request_id: %v", ev.Metadata)
return
}
// Only the request id, kind, and deadline stay on argv: they are
// daemon-issued and non-sensitive. The remote-influenced fields go
// through the child's environment.
args := []string{
"--approval-request-id=" + requestID,
"--approval-kind=" + ev.Metadata["kind"],
"--approval-initiator=" + ev.Metadata["initiator"],
"--approval-peer-name=" + ev.Metadata["peer_name"],
"--approval-source-ip=" + ev.Metadata["source_ip"],
"--approval-username=" + ev.Metadata["username"],
"--approval-expires-at=" + ev.Metadata["expires_at"],
"--approval-key-fingerprint=" + ev.Metadata["peer_pubkey"],
"--approval-subject=" + ev.UserMessage,
}
go s.eventHandler.runSelfCommand(s.ctx, "approval", args...)
env := append(os.Environ(),
envApprovalInitiator+"="+ev.Metadata["initiator"],
envApprovalPeerName+"="+ev.Metadata["peer_name"],
envApprovalSourceIP+"="+ev.Metadata["source_ip"],
envApprovalUsername+"="+ev.Metadata["username"],
envApprovalKeyFingerprint+"="+ev.Metadata["peer_pubkey"],
envApprovalSubject+"="+ev.UserMessage,
)
go s.runApprovalCommand(s.ctx, env, args)
}
// runApprovalCommand forks netbird-ui to render the approval dialog,
// inheriting the parent environment plus the approval-specific variables. It
// mirrors runSelfCommand but sets cmd.Env so the sensitive metadata never
// appears on the child's argv.
func (s *serviceClient) runApprovalCommand(ctx context.Context, env, args []string) {
proc, err := os.Executable()
if err != nil {
log.Errorf("get executable path: %v", err)
return
}
cmdArgs := append([]string{"--approval=true", "--daemon-addr=" + s.addr}, args...)
cmd := exec.CommandContext(ctx, proc, cmdArgs...)
cmd.Env = env
if out := s.attachOutput(cmd); out != nil {
defer func() {
if err := out.Close(); err != nil {
log.Errorf("close log file %s: %v", s.logFile, err)
}
}()
}
log.Printf("running approval command: %s", cmd.String())
if err := cmd.Run(); err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
log.Printf("approval command failed with exit code %d", exitErr.ExitCode())
}
}
}
// showApprovalUI runs the dialog on the forked process's fyne main loop
+9 -21
View File
@@ -101,13 +101,13 @@ func main() {
approvalRequest: approvalRequest{
requestID: flags.approvalRequestID,
kind: flags.approvalKind,
initiator: flags.approvalInitiator,
peerName: flags.approvalPeerName,
sourceIP: flags.approvalSourceIP,
username: flags.approvalUsername,
subject: flags.approvalSubject,
initiator: os.Getenv(envApprovalInitiator),
peerName: os.Getenv(envApprovalPeerName),
sourceIP: os.Getenv(envApprovalSourceIP),
username: os.Getenv(envApprovalUsername),
subject: os.Getenv(envApprovalSubject),
expiresAt: flags.approvalExpiresAt,
keyFingerprint: flags.approvalKeyFingerprint,
keyFingerprint: os.Getenv(envApprovalKeyFingerprint),
},
})
@@ -154,15 +154,9 @@ type cliFlags struct {
showUpdateVersion string
showApproval bool
approvalRequestID string
approvalKind string
approvalInitiator string
approvalPeerName string
approvalSourceIP string
approvalUsername string
approvalSubject string
approvalExpiresAt string
approvalKeyFingerprint string
approvalRequestID string
approvalKind string
approvalExpiresAt string
}
// parseFlags reads and returns all needed command-line flags.
@@ -187,13 +181,7 @@ func parseFlags() *cliFlags {
flag.BoolVar(&flags.showApproval, "approval", false, "show inbound-connection approval prompt window")
flag.StringVar(&flags.approvalRequestID, "approval-request-id", "", "approval prompt: daemon-issued request id")
flag.StringVar(&flags.approvalKind, "approval-kind", "", "approval prompt: subsystem kind (vnc, ssh, ...)")
flag.StringVar(&flags.approvalInitiator, "approval-initiator", "", "approval prompt: display name of the user who initiated the connection")
flag.StringVar(&flags.approvalPeerName, "approval-peer-name", "", "approval prompt: remote peer FQDN")
flag.StringVar(&flags.approvalSourceIP, "approval-source-ip", "", "approval prompt: remote source IP")
flag.StringVar(&flags.approvalUsername, "approval-username", "", "approval prompt: requested OS username")
flag.StringVar(&flags.approvalSubject, "approval-subject", "", "approval prompt: human-readable subject line")
flag.StringVar(&flags.approvalExpiresAt, "approval-expires-at", "", "approval prompt: RFC3339 deadline at which the daemon auto-denies")
flag.StringVar(&flags.approvalKeyFingerprint, "approval-key-fingerprint", "", "approval prompt: hex-encoded Noise static pubkey of the connecting client")
flag.Parse()
return &flags
}