From 0ed0fb5817551b823500800ee236545075368b51 Mon Sep 17 00:00:00 2001 From: David Schroeder Date: Sun, 26 Jul 2026 10:33:50 -0500 Subject: [PATCH] update --- internal/app/audit_test.go | 4 ++- internal/app/authorization.go | 30 ++++------------ internal/app/download.go | 47 +++++++++----------------- internal/app/server.go | 1 - internal/app/server_test.go | 1 - internal/app/templates/audit.html | 2 +- internal/app/templates/components.html | 6 ++-- migrations/004_remove_lan_ip.sql | 7 ++++ 8 files changed, 35 insertions(+), 63 deletions(-) create mode 100644 migrations/004_remove_lan_ip.sql diff --git a/internal/app/audit_test.go b/internal/app/audit_test.go index ad156e7..98fb28d 100644 --- a/internal/app/audit_test.go +++ b/internal/app/audit_test.go @@ -77,6 +77,9 @@ func TestAuditQueryUsesPlaceholders(t *testing.T) { if strings.Contains(query, "INTERVAL") { t.Fatal("all-time query must not include a time restriction") } + if strings.Contains(query, "lan_ip") { + t.Fatal("audit query must use the single source_ip column") + } if !strings.HasSuffix(query, "ORDER BY ae.created_at DESC LIMIT ?") { t.Fatalf("query has unexpected limit: %s", query) } @@ -88,7 +91,6 @@ func TestAuditQueryUsesPlaceholders(t *testing.T) { "sentinelone-linux", "install-rmm", "10.10.1.25", - "10.10.1.25", 250, } if !reflect.DeepEqual(arguments, expectedArguments) { diff --git a/internal/app/authorization.go b/internal/app/authorization.go index 90c08e9..78a5516 100644 --- a/internal/app/authorization.go +++ b/internal/app/authorization.go @@ -207,7 +207,7 @@ func (s *Server) listAuditEventTypes(r *http.Request) ([]string, error) { func auditQuery(filters auditFilters, limit int) (string, []any) { query := `SELECT ae.event_type, COALESCE(a.customer_label, ''), ae.actor, - ae.hostname, ae.package_slug, ae.source_ip, ae.lan_ip, + ae.hostname, ae.package_slug, ae.source_ip, ae.details, ae.created_at FROM audit_events ae LEFT JOIN authorizations a ON a.id = ae.authorization_id @@ -244,8 +244,8 @@ func auditQuery(filters auditFilters, limit int) (string, []any) { arguments = append(arguments, filter.value) } if filters.SourceIP != "" { - query += " AND (LOCATE(?, ae.source_ip) > 0 OR LOCATE(?, ae.lan_ip) > 0)" - arguments = append(arguments, filters.SourceIP, filters.SourceIP) + query += " AND LOCATE(?, ae.source_ip) > 0" + arguments = append(arguments, filters.SourceIP) } query += " ORDER BY ae.created_at DESC LIMIT ?" arguments = append(arguments, limit) @@ -274,7 +274,6 @@ func (s *Server) listAuditEvents(r *http.Request, filters auditFilters, limit in &record.Hostname, &record.PackageSlug, &record.SourceIP, - &record.LANIP, &record.Details, &record.CreatedAt, ); err != nil { @@ -623,23 +622,6 @@ func (s *Server) audit( packageSlug string, sourceIP string, details string, -) error { - return s.auditWithNetwork( - ctx, eventType, user, authorizationID, hostname, packageSlug, - sourceIP, "", details, - ) -} - -func (s *Server) auditWithNetwork( - ctx context.Context, - eventType string, - user string, - authorizationID *uint64, - hostname string, - packageSlug string, - sourceIP string, - lanIP string, - details string, ) error { var authID any if authorizationID != nil { @@ -649,9 +631,9 @@ func (s *Server) auditWithNetwork( ctx, `INSERT INTO audit_events (event_type, actor, authorization_id, hostname, package_slug, - source_ip, lan_ip, details) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, - eventType, user, authID, hostname, packageSlug, sourceIP, lanIP, details, + source_ip, details) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + eventType, user, authID, hostname, packageSlug, sourceIP, details, ) return err } diff --git a/internal/app/download.go b/internal/app/download.go index 2a26d43..441c631 100644 --- a/internal/app/download.go +++ b/internal/app/download.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "net" "net/http" "net/url" "strings" @@ -17,7 +16,6 @@ type exchangeRequest struct { Code string `json:"code"` HostFingerprint string `json:"host_fingerprint"` Hostname string `json:"hostname"` - LANIP string `json:"lan_ip,omitempty"` RequestedAction string `json:"requested_action,omitempty"` RequestedPackage string `json:"requested_package,omitempty"` } @@ -59,17 +57,8 @@ func (s *Server) handleExchange(w http.ResponseWriter, r *http.Request) { request.Code = normalizeCode(request.Code) request.HostFingerprint = strings.TrimSpace(request.HostFingerprint) request.Hostname = strings.TrimSpace(request.Hostname) - request.LANIP = strings.TrimSpace(request.LANIP) request.RequestedAction = strings.TrimSpace(request.RequestedAction) request.RequestedPackage = strings.TrimSpace(request.RequestedPackage) - if request.LANIP != "" { - parsedLANIP := net.ParseIP(request.LANIP) - if parsedLANIP == nil { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "lan_ip must be a valid IP address"}) - return - } - request.LANIP = parsedLANIP.String() - } if request.Code == "" || len(request.HostFingerprint) < 16 || request.Hostname == "" || len(request.Hostname) > 255 || (request.RequestedAction != "" && !validSlug(request.RequestedAction)) || @@ -86,12 +75,12 @@ func (s *Server) handleExchange(w http.ResponseWriter, r *http.Request) { status = http.StatusForbidden message = "authorization is invalid, expired, revoked, or at its host limit" } - _ = s.auditWithNetwork(r.Context(), "code_exchange_failed", "", nil, - request.Hostname, "", sourceIP, request.LANIP, err.Error()) + _ = s.audit(r.Context(), "code_exchange_failed", "", nil, + request.Hostname, "", sourceIP, err.Error()) writeJSON(w, status, map[string]string{"error": message}) return } - _ = s.auditWithNetwork( + _ = s.audit( r.Context(), "code_exchanged", "", @@ -99,7 +88,6 @@ func (s *Server) handleExchange(w http.ResponseWriter, r *http.Request) { request.Hostname, request.RequestedPackage, sourceIP, - request.LANIP, "requested_action="+request.RequestedAction, ) writeJSON(w, http.StatusOK, response) @@ -212,9 +200,9 @@ func (s *Server) exchangeDeploymentCode( result, err := tx.ExecContext( r.Context(), `INSERT INTO authorization_hosts - (authorization_id, host_fingerprint, hostname, lan_ip) - VALUES (?, ?, ?, ?)`, - authorizationID, fingerprintHash[:], request.Hostname, request.LANIP, + (authorization_id, host_fingerprint, hostname) + VALUES (?, ?, ?)`, + authorizationID, fingerprintHash[:], request.Hostname, ) if err != nil { return response, 0, err @@ -228,10 +216,9 @@ func (s *Server) exchangeDeploymentCode( r.Context(), `UPDATE authorization_hosts SET hostname = ?, - lan_ip = COALESCE(NULLIF(?, ''), lan_ip), last_seen_at = UTC_TIMESTAMP(6) WHERE id = ?`, - request.Hostname, request.LANIP, hostID, + request.Hostname, hostID, ) if err != nil { return response, 0, err @@ -343,12 +330,11 @@ func (s *Server) handlePackageDownload(w http.ResponseWriter, r *http.Request) { var packageInfo packageRecord var authorizationID uint64 var hostname string - var lanIP string err := s.db.QueryRowContext( r.Context(), `SELECT p.id, p.slug, p.display_name, p.package_name, p.package_version, p.file_name, p.sha256, p.enabled, - ds.authorization_id, ah.hostname, ah.lan_ip + ds.authorization_id, ah.hostname FROM download_sessions ds JOIN authorizations a ON a.id = ds.authorization_id JOIN authorization_hosts ah ON ah.id = ds.authorization_host_id @@ -373,7 +359,6 @@ func (s *Server) handlePackageDownload(w http.ResponseWriter, r *http.Request) { &packageInfo.Enabled, &authorizationID, &hostname, - &lanIP, ) if errors.Is(err, sql.ErrNoRows) { writeJSON(w, http.StatusForbidden, map[string]string{"error": "package is not authorized"}) @@ -402,15 +387,15 @@ func (s *Server) handlePackageDownload(w http.ResponseWriter, r *http.Request) { upstreamRequest.SetBasicAuth(s.cfg.GiteaPackageUser, s.cfg.GiteaPackageToken) upstreamResponse, err := s.packageClient.Do(upstreamRequest) if err != nil { - _ = s.auditWithNetwork(r.Context(), "package_download_failed", "", - &authorizationID, hostname, slug, s.clientIP(r), lanIP, err.Error()) + _ = s.audit(r.Context(), "package_download_failed", "", + &authorizationID, hostname, slug, s.clientIP(r), err.Error()) writeJSON(w, http.StatusBadGateway, map[string]string{"error": "package registry is unavailable"}) return } defer upstreamResponse.Body.Close() if upstreamResponse.StatusCode != http.StatusOK { - _ = s.auditWithNetwork(r.Context(), "package_download_failed", "", - &authorizationID, hostname, slug, s.clientIP(r), lanIP, upstreamResponse.Status) + _ = s.audit(r.Context(), "package_download_failed", "", + &authorizationID, hostname, slug, s.clientIP(r), upstreamResponse.Status) writeJSON(w, http.StatusBadGateway, map[string]string{"error": "package registry rejected the request"}) return } @@ -421,10 +406,10 @@ func (s *Server) handlePackageDownload(w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "no-store") w.WriteHeader(http.StatusOK) if _, err := io.Copy(w, upstreamResponse.Body); err != nil { - _ = s.auditWithNetwork(r.Context(), "package_download_failed", "", - &authorizationID, hostname, slug, s.clientIP(r), lanIP, err.Error()) + _ = s.audit(r.Context(), "package_download_failed", "", + &authorizationID, hostname, slug, s.clientIP(r), err.Error()) return } - _ = s.auditWithNetwork(r.Context(), "package_downloaded", "", - &authorizationID, hostname, slug, s.clientIP(r), lanIP, "") + _ = s.audit(r.Context(), "package_downloaded", "", + &authorizationID, hostname, slug, s.clientIP(r), "") } diff --git a/internal/app/server.go b/internal/app/server.go index 3a64aed..b69f49f 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -75,7 +75,6 @@ type auditRecord struct { Hostname string PackageSlug string SourceIP string - LANIP string Details string CreatedAt time.Time } diff --git a/internal/app/server_test.go b/internal/app/server_test.go index 4930ab9..34ce0f2 100644 --- a/internal/app/server_test.go +++ b/internal/app/server_test.go @@ -73,7 +73,6 @@ func TestPackageAndAuditTemplatesExecute(t *testing.T) { CustomerLabel: "Acme cluster refresh", Hostname: "pve01", SourceIP: "203.0.113.10", - LANIP: "10.10.1.25", CreatedAt: time.Now(), }} if err := templates.ExecuteTemplate(io.Discard, "audit.html", data); err != nil { diff --git a/internal/app/templates/audit.html b/internal/app/templates/audit.html index 9893a5e..5067fba 100644 --- a/internal/app/templates/audit.html +++ b/internal/app/templates/audit.html @@ -42,7 +42,7 @@ - +
diff --git a/internal/app/templates/components.html b/internal/app/templates/components.html index 5cc162b..b1d8f71 100644 --- a/internal/app/templates/components.html +++ b/internal/app/templates/components.html @@ -29,7 +29,7 @@ Event Customer / deployment User / host / package - WAN / LAN / details + IP / Details
{{range .AuditEvents}}
@@ -46,9 +46,7 @@ {{if .PackageSlug}}{{.PackageSlug}}{{end}}
- {{if .SourceIP}}WAN: {{.SourceIP}}{{end}} - {{if .LANIP}}LAN: {{.LANIP}}{{end}} - {{if and (not .SourceIP) (not .LANIP)}}{{end}} + {{if .SourceIP}}{{.SourceIP}}{{else}}{{end}} {{if .Details}}{{.Details}}{{end}}
diff --git a/migrations/004_remove_lan_ip.sql b/migrations/004_remove_lan_ip.sql new file mode 100644 index 0000000..da33a77 --- /dev/null +++ b/migrations/004_remove_lan_ip.sql @@ -0,0 +1,7 @@ +ALTER TABLE authorization_hosts + DROP COLUMN IF EXISTS lan_ip; + +ALTER TABLE audit_events + DROP COLUMN IF EXISTS lan_ip; + +INSERT IGNORE INTO schema_migrations (version) VALUES (4);