package reportscollector import ( "encoding/json" "net/http" "time" "github.com/jhillyerd/enmime" ) type legacyCSPReport struct { DocumentURI string `json:"document-uri"` Referrer string `json:"referrer"` ViolatedDirective string `json:"violated-directive"` EffectiveDirective string `json:"effective-directive"` OriginalPolicy string `json:"original-policy"` Disposition string `json:"disposition"` BlockedURI string `json:"blocked-uri"` LineNumber int `json:"line-number"` SourceFile string `json:"source-file"` StatusCode int `json:"status-code"` } type legacyCSPReportContainer struct { Report *legacyCSPReport `json:"csp-report"` } type LegacyCSPHandler struct{} func (h *LegacyCSPHandler) Name() string { return "legacy-csp" } func (h *LegacyCSPHandler) Parse(contentType string, req *http.Request) ([]Event, error) { if contentType != "application/csp-report" { return nil, ErrNoMatch } var cnt legacyCSPReportContainer if err := json.NewDecoder(req.Body).Decode(&cnt); err != nil { return nil, err } if cnt.Report == nil { return nil, nil } return []Event{h.eventFromReport(req, cnt.Report)}, nil } func (h *LegacyCSPHandler) ParseMIME(*enmime.Part) ([]Event, error) { return nil, ErrNoMatch } func (h *LegacyCSPHandler) eventFromReport(req *http.Request, report *legacyCSPReport) Event { e := make(Event) if asn, ok := lookupASN(getRemoteIP(req)); ok { e.Set("asn", asn) } e.Set("type", "csp") e.Set("event_timestamp", time.Now()) e.Set("url", report.DocumentURI) e.Set("domain", domainFromURL(report.DocumentURI)) e.Set("user_agent", req.Header.Get("User-Agent")) // TODO: use the same fields as report-to CSP reports. e.Set("csp_violated_directive", report.ViolatedDirective) e.Set("csp_blocked_uri", report.BlockedURI) e.Set("csp_source_file", report.SourceFile) e.Set("csp_line_number", report.LineNumber) e.Set("csp_status_code", report.StatusCode) return e }