Skip to content
Snippets Groups Projects
csp.go 1.95 KiB
Newer Older
  • Learn to ignore specific revisions
  • ale's avatar
    ale committed
    package reportscollector
    
    import (
    	"encoding/json"
    	"net/http"
    	"time"
    
    
    	"github.com/jhillyerd/enmime"
    
    ale's avatar
    ale committed
    )
    
    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" }
    
    
    ale's avatar
    ale committed
    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
    }
    
    
    ale's avatar
    ale committed
    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
    }