Skip to content

Commit

Permalink
Merge pull request #218 from cerberauth/add-sqa-errors-tracking
Browse files Browse the repository at this point in the history
Add SQA errors and more metrics
  • Loading branch information
emmanuelgautier authored Nov 9, 2024
2 parents ea66b5d + 513da1e commit c435cf5
Show file tree
Hide file tree
Showing 28 changed files with 332 additions and 231 deletions.
23 changes: 8 additions & 15 deletions api/curl.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package api
import (
"net/http"

"github.com/cerberauth/vulnapi/internal/analytics"
"github.com/cerberauth/vulnapi/internal/request"
"github.com/cerberauth/vulnapi/scan"
"github.com/cerberauth/vulnapi/scenario"
"github.com/cerberauth/x/analyticsx"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

type NewURLScanRequest struct {
Expand All @@ -20,17 +19,14 @@ type NewURLScanRequest struct {
Opts *ScanOptions `json:"options"`
}

var serverApiUrlTracer = otel.Tracer("server/api/url")

func (h *Handler) ScanURL(ctx *gin.Context) {
var form NewURLScanRequest
if err := ctx.ShouldBindJSON(&form); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
analyticsx.TrackEvent(ctx, serverApiUrlTracer, "Scan URL", []attribute.KeyValue{
attribute.String("method", form.Method),
})
traceCtx, span := tracer.Start(ctx.Request.Context(), "Scan URL")
defer span.End()

opts := parseScanOptions(form.Opts)
opts.Header = ctx.Request.Header
Expand All @@ -42,21 +38,18 @@ func (h *Handler) ScanURL(ctx *gin.Context) {
ExcludeScans: form.Opts.ExcludeScans,
})
if err != nil {
analyticsx.TrackError(ctx, serverApiUrlTracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {})
reporter, _, err := s.Execute(traceCtx, nil)
if err != nil {
analyticsx.TrackError(ctx, serverApiUrlTracer, err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

if reporter.HasIssue() {
analyticsx.TrackEvent(ctx, serverApiUrlTracer, "Issue Found", nil)
}
analytics.TrackScanReport(traceCtx, reporter)

ctx.JSON(http.StatusOK, HTTPResponseReports{
Reports: reporter.GetScanReports(),
Expand Down
24 changes: 11 additions & 13 deletions api/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package api
import (
"net/http"

"github.com/cerberauth/vulnapi/internal/analytics"
"github.com/cerberauth/vulnapi/internal/request"
"github.com/cerberauth/vulnapi/scan"
"github.com/cerberauth/vulnapi/scenario"
"github.com/cerberauth/x/analyticsx"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

type NewGraphQLScanRequest struct {
Expand All @@ -18,16 +17,16 @@ type NewGraphQLScanRequest struct {
Opts *ScanOptions `json:"options"`
}

var serverApiGraphQLTracer = otel.Tracer("server/api/graphql")

func (h *Handler) ScanGraphQL(ctx *gin.Context) {
var form NewGraphQLScanRequest
if err := ctx.ShouldBindJSON(&form); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

analyticsx.TrackEvent(ctx, serverApiGraphQLTracer, "Scan GraphQL", []attribute.KeyValue{})
traceCtx, span := tracer.Start(ctx, "Scan GraphQL")
defer span.End()

opts := parseScanOptions(form.Opts)
opts.Header = ctx.Request.Header
opts.Cookies = ctx.Request.Cookies()
Expand All @@ -38,21 +37,20 @@ func (h *Handler) ScanGraphQL(ctx *gin.Context) {
ExcludeScans: form.Opts.ExcludeScans,
})
if err != nil {
analyticsx.TrackError(ctx, serverApiGraphQLTracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {})
reporter, _, err := s.Execute(traceCtx, nil)
if err != nil {
analyticsx.TrackError(ctx, serverApiGraphQLTracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

if reporter.HasIssue() {
analyticsx.TrackEvent(ctx, serverApiGraphQLTracer, "Issue Found", nil)
}
analytics.TrackScanReport(traceCtx, reporter)

ctx.JSON(http.StatusOK, HTTPResponseReports{
Reports: reporter.GetScanReports(),
Expand Down
7 changes: 6 additions & 1 deletion api/handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package api

import "github.com/gin-gonic/gin"
import (
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
)

var tracer = otel.Tracer("server/api")

type Handler struct{}

Expand Down
35 changes: 18 additions & 17 deletions api/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"encoding/json"
"net/http"

"github.com/cerberauth/vulnapi/internal/analytics"
"github.com/cerberauth/vulnapi/internal/auth"
"github.com/cerberauth/vulnapi/internal/request"
"github.com/cerberauth/vulnapi/openapi"
"github.com/cerberauth/vulnapi/scan"
"github.com/cerberauth/vulnapi/scenario"
"github.com/cerberauth/x/analyticsx"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

type NewOpenAPIScanRequest struct {
Expand All @@ -24,29 +23,31 @@ type NewOpenAPIScanRequest struct {
Opts *ScanOptions `json:"options"`
}

var serverApiOpenAPITracer = otel.Tracer("server/api/openapi")

func (h *Handler) ScanOpenAPI(ctx *gin.Context) {
var form NewOpenAPIScanRequest
if err := ctx.ShouldBindJSON(&form); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

openapi, err := openapi.LoadFromData(ctx, []byte(form.Schema))
traceCtx, span := tracer.Start(ctx, "Scan OpenAPI")
defer span.End()

openapi, err := openapi.LoadFromData(traceCtx, []byte(form.Schema))
if err != nil {
analyticsx.TrackError(ctx, serverApiOpenAPITracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

if err := openapi.Validate(ctx); err != nil {
analyticsx.TrackError(ctx, serverApiOpenAPITracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

analyticsx.TrackEvent(ctx, serverApiOpenAPITracer, "Scan OpenAPI", []attribute.KeyValue{})
opts := parseScanOptions(form.Opts)
opts.Header = ctx.Request.Header
opts.Cookies = ctx.Request.Cookies()
Expand All @@ -64,28 +65,28 @@ func (h *Handler) ScanOpenAPI(ctx *gin.Context) {
ExcludeScans: form.Opts.ExcludeScans,
})
if err != nil {
analyticsx.TrackError(ctx, serverApiOpenAPITracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {})
reporter, _, err := s.Execute(traceCtx, nil)
if err != nil {
analyticsx.TrackError(ctx, serverApiOpenAPITracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

if reporter.HasIssue() {
analyticsx.TrackEvent(ctx, serverApiOpenAPITracer, "Issue Found", nil)
}
analytics.TrackScanReport(traceCtx, reporter)

response := HTTPResponseReports{
Reports: reporter.GetScanReports(),
}
_, err = json.Marshal(response)
if err != nil {
analyticsx.TrackError(ctx, serverApiOpenAPITracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
Expand Down
24 changes: 13 additions & 11 deletions cmd/discover/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"log"
"net/http"

"github.com/cerberauth/vulnapi/internal/analytics"
internalCmd "github.com/cerberauth/vulnapi/internal/cmd"
"github.com/cerberauth/vulnapi/internal/cmd/printtable"
"github.com/cerberauth/vulnapi/scan"
"github.com/cerberauth/vulnapi/scenario"
"github.com/cerberauth/x/analyticsx"
"github.com/schollz/progressbar/v3"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

func NewAPICmd() (apiCmd *cobra.Command) {
Expand All @@ -21,14 +20,15 @@ func NewAPICmd() (apiCmd *cobra.Command) {
Short: "Discover api endpoints and server information",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
tracer := otel.Tracer("discover")
baseUrl := args[0]

analyticsx.TrackEvent(ctx, tracer, "Discover API", []attribute.KeyValue{})
ctx, span := tracer.Start(cmd.Context(), "Discover API")
defer span.End()

client, err := internalCmd.NewHTTPClientFromArgs(internalCmd.GetRateLimit(), internalCmd.GetProxy(), internalCmd.GetHeaders(), internalCmd.GetCookies())
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}

Expand All @@ -37,7 +37,8 @@ func NewAPICmd() (apiCmd *cobra.Command) {
ExcludeScans: internalCmd.GetExcludeScans(),
})
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}

Expand All @@ -47,18 +48,19 @@ func NewAPICmd() (apiCmd *cobra.Command) {
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
reporter, _, err := s.Execute(ctx, func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}

internalCmd.TrackScanReport(ctx, tracer, reporter)
analytics.TrackScanReport(ctx, reporter)
printtable.WellKnownPathsScanReport(reporter)
printtable.FingerprintScanReport(reporter)
},
Expand Down
24 changes: 13 additions & 11 deletions cmd/discover/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"fmt"
"log"

"github.com/cerberauth/vulnapi/internal/analytics"
internalCmd "github.com/cerberauth/vulnapi/internal/cmd"
"github.com/cerberauth/vulnapi/internal/cmd/printtable"
"github.com/cerberauth/vulnapi/scan"
"github.com/cerberauth/vulnapi/scenario"
"github.com/cerberauth/x/analyticsx"
"github.com/schollz/progressbar/v3"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

func NewDomainCmd() (domainCmd *cobra.Command) {
Expand All @@ -21,14 +20,15 @@ func NewDomainCmd() (domainCmd *cobra.Command) {
Short: "Discover subdomains with API endpoints",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
tracer := otel.Tracer("discover")
domain := args[0]

analyticsx.TrackEvent(ctx, tracer, "Discover Domain", []attribute.KeyValue{})
ctx, span := tracer.Start(cmd.Context(), "Discover Domain")
defer span.End()

client, err := internalCmd.NewHTTPClientFromArgs(internalCmd.GetRateLimit(), internalCmd.GetProxy(), internalCmd.GetHeaders(), internalCmd.GetCookies())
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}

Expand All @@ -38,7 +38,8 @@ func NewDomainCmd() (domainCmd *cobra.Command) {
ExcludeScans: internalCmd.GetExcludeScans(),
})
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}
fmt.Printf("Found %d Domains\n", len(scans))
Expand All @@ -53,18 +54,19 @@ func NewDomainCmd() (domainCmd *cobra.Command) {
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
reporter, _, err := s.Execute(ctx, func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
log.Fatal(err)
}

internalCmd.TrackScanReport(ctx, tracer, reporter)
analytics.TrackScanReport(ctx, reporter)
printtable.WellKnownPathsScanReport(reporter)
printtable.FingerprintScanReport(reporter)
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/discover/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package discover

import (
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
)

var tracer = otel.Tracer("cmd/discover")

func NewDiscoverCmd() (discoverCmd *cobra.Command) {
discoverCmd = &cobra.Command{
Use: "discover [type]",
Expand Down
Loading

0 comments on commit c435cf5

Please sign in to comment.