Skip to content

Commit

Permalink
Merge pull request #198 from cerberauth/ci-lint
Browse files Browse the repository at this point in the history
Add golangci lint
  • Loading branch information
emmanuelgautier authored Oct 6, 2024
2 parents 6eb544b + 553af78 commit d48e9d9
Show file tree
Hide file tree
Showing 19 changed files with 133 additions and 52 deletions.
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ concurrency:
cancel-in-progress: true

jobs:
build:
test:
runs-on: ubuntu-latest

permissions:
contents: read
checks: write

steps:
- uses: actions/checkout@v4

Expand All @@ -29,6 +33,9 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}

- name: Lint
uses: golangci/golangci-lint-action@v6

- name: Build
run: go build -v ./...

Expand All @@ -41,7 +48,7 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

publish:
needs: build
needs: test
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')

Expand Down
26 changes: 26 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
linters:
enable:
- errcheck
- goconst
- gocritic
- gofmt
- goimports
- gosec
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused

linters-settings:
gosec:
excludes:
- G101
- G107

issues:
exclude-files:
- ".+_test.go"


2 changes: 2 additions & 0 deletions cmd/discover/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ func NewAPICmd() (apiCmd *cobra.Command) {
var bar *progressbar.ProgressBar
if !internalCmd.GetNoProgress() {
bar = internalCmd.NewProgressBar(len(s.GetOperationsScans()))
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
Expand Down
2 changes: 2 additions & 0 deletions cmd/discover/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ func NewDomainCmd() (domainCmd *cobra.Command) {
var bar *progressbar.ProgressBar
if !internalCmd.GetNoProgress() {
bar = internalCmd.NewProgressBar(len(s.GetOperationsScans()))
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
Expand Down
5 changes: 4 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ func NewRootCmd(projectVersion string) (cmd *cobra.Command) {
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if !sqaOptOut {
ctx := cmd.Context()
analytics.NewAnalytics(ctx, projectVersion)
_, err := analytics.NewAnalytics(ctx, projectVersion)
if err != nil {
fmt.Println("Failed to initialize analytics:", err)
}
}
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
Expand Down
8 changes: 7 additions & 1 deletion cmd/scan/curl.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ func NewCURLScanCmd() (scanCmd *cobra.Command) {
var bar *progressbar.ProgressBar
if !internalCmd.GetNoProgress() {
bar = internalCmd.NewProgressBar(len(s.GetOperationsScans()))
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
Expand All @@ -66,7 +68,11 @@ func NewCURLScanCmd() (scanCmd *cobra.Command) {
}

internalCmd.TrackScanReport(ctx, tracer, reporter)
internalCmd.PrintOrExportReport(internalCmd.GetOutputFormat(), internalCmd.GetOutputTransport(), reporter)
err = internalCmd.PrintOrExportReport(internalCmd.GetOutputFormat(), internalCmd.GetOutputTransport(), reporter)
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
log.Fatal(err)
}
},
}

Expand Down
8 changes: 7 additions & 1 deletion cmd/scan/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ func NewGraphQLScanCmd() (scanCmd *cobra.Command) {
var bar *progressbar.ProgressBar
if !internalCmd.GetNoProgress() {
bar = internalCmd.NewProgressBar(len(s.GetOperationsScans()))
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
Expand All @@ -58,7 +60,11 @@ func NewGraphQLScanCmd() (scanCmd *cobra.Command) {
}

internalCmd.TrackScanReport(ctx, tracer, reporter)
internalCmd.PrintOrExportReport(internalCmd.GetOutputFormat(), internalCmd.GetOutputTransport(), reporter)
err = internalCmd.PrintOrExportReport(internalCmd.GetOutputFormat(), internalCmd.GetOutputTransport(), reporter)
if err != nil {
analyticsx.TrackError(ctx, tracer, err)
log.Fatal(err)
}
},
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/scan/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ func NewOpenAPIScanCmd() (scanCmd *cobra.Command) {
var bar *progressbar.ProgressBar
if !internalCmd.GetNoProgress() {
bar = internalCmd.NewProgressBar(len(s.GetOperationsScans()))
// nolint:errcheck
defer bar.Finish()
}
reporter, _, err := s.Execute(func(operationScan *scan.OperationScan) {
if bar != nil {
// nolint:errcheck
bar.Add(1)
}
})
Expand Down
8 changes: 6 additions & 2 deletions internal/analytics/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func NewAnalytics(ctx context.Context, projectVersion string) (*sdktrace.TracerP
return tracerProvider, err
}

func Close() {
tracerProvider.Shutdown(context.Background())
func Close() error {
if tracerProvider == nil {
return nil
}

return tracerProvider.Shutdown(context.Background())
}
7 changes: 4 additions & 3 deletions internal/cmd/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ func PrintOrExportReport(format string, transport string, report *report.Reporte
}

var outputMessage string
if !report.HasVulnerability() {
switch {
case !report.HasVulnerability():
outputMessage = "Success: No vulnerabilities detected!"
} else if report.HasHighRiskOrHigherSeverityVulnerability() {
case report.HasHighRiskOrHigherSeverityVulnerability():
outputMessage = "Error: There are some high-risk issues. It's advised to take immediate action."
} else {
default:
outputMessage = "Warning: There are some issues. It's advised to take action."
}

Expand Down
9 changes: 5 additions & 4 deletions internal/cmd/printtable/report_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ func NewFullScanVulnerabilityReports(reports []*report.Report) []*ScanVulnerabil
}

func severityTableColor(v *report.VulnerabilityReport) int {
if v.IsLowRiskSeverity() || v.IsInfoRiskSeverity() {
switch {
case v.IsLowRiskSeverity() || v.IsInfoRiskSeverity():
return tablewriter.BgBlueColor
} else if v.IsMediumRiskSeverity() {
case v.IsMediumRiskSeverity():
return tablewriter.BgYellowColor
} else if v.IsHighRiskSeverity() {
case v.IsHighRiskSeverity():
return tablewriter.BgRedColor
} else if v.IsCriticalRiskSeverity() {
case v.IsCriticalRiskSeverity():
return tablewriter.BgHiRedColor
}

Expand Down
2 changes: 1 addition & 1 deletion internal/request/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func NewClient(opts NewClientOptions) *Client {
opts.Cookies = []*http.Cookie{}
}

var proxy func(*http.Request) (*url.URL, error) = nil
var proxy func(*http.Request) (*url.URL, error)
if opts.ProxyURL != nil && opts.ProxyURL.String() != "" {
proxy = http.ProxyURL(opts.ProxyURL)
} else {
Expand Down
18 changes: 11 additions & 7 deletions internal/request/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Operation struct {
*Client `json:"-" yaml:"-"`

Method string `json:"method" yaml:"method"`
URL url.URL `json:"url,string" yaml:"url,string"`
URL url.URL `json:"url" yaml:"url"`
Body *bytes.Buffer `json:"body,omitempty" yaml:"body,omitempty"`
Cookies []*http.Cookie `json:"cookies,omitempty" yaml:"cookies,omitempty"`
Header http.Header `json:"header,omitempty" yaml:"header,omitempty"`
Expand Down Expand Up @@ -63,11 +63,12 @@ func NewOperation(method string, operationUrl string, body *bytes.Buffer, client
func (operation *Operation) IsReachable() error {
host := operation.URL.Host
if _, _, err := net.SplitHostPort(host); err != nil {
if operation.URL.Scheme == "http" {
switch operation.URL.Scheme {
case "http":
host += ":80"
} else if operation.URL.Scheme == "https" {
case "https":
host += ":443"
} else {
default:
return errors.New("unsupported scheme")
}
}
Expand All @@ -76,11 +77,14 @@ func (operation *Operation) IsReachable() error {
return err
}

func NewOperationFromRequest(r *Request) *Operation {
func NewOperationFromRequest(r *Request) (*Operation, error) {
var body bytes.Buffer
if r.Body != nil {
tee := io.TeeReader(r.Body, &body)
io.ReadAll(tee)
_, err := io.ReadAll(tee)
if err != nil {
return nil, err
}
}

return &Operation{
Expand All @@ -91,7 +95,7 @@ func NewOperationFromRequest(r *Request) *Operation {
Body: &body,

SecuritySchemes: []auth.SecurityScheme{auth.NewNoAuthSecurityScheme()},
}
}, nil
}

func (operation *Operation) WithOpenapiOperation(openapiOperation openapi3.Operation) *Operation {
Expand Down
3 changes: 2 additions & 1 deletion internal/request/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ func TestNewOperationFromRequest(t *testing.T) {
r.WithHeader(header)
cookies := []*http.Cookie{}
r.WithCookies(cookies)
operation := request.NewOperationFromRequest(r)
operation, err := request.NewOperationFromRequest(r)

assert.NoError(t, err)
assert.Equal(t, r.URL.String(), operation.URL.String())
assert.Equal(t, r.Method, operation.Method)
}
Expand Down
6 changes: 4 additions & 2 deletions openapi/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ func (openapi *OpenAPI) Operations(client *request.Client, securitySchemes auth.
}
}

body := bytes.NewBuffer(nil)
var body *bytes.Buffer
var mediaType string
if o.RequestBody != nil {
mediaType := "application/json"
body, mediaType = getRequestBodyValue(o.RequestBody.Value)
header.Set("Content-Type", mediaType)
} else {
body = bytes.NewBuffer(nil)
}

operation, err := request.NewOperation(method, operationUrl.String(), body, client)
Expand Down
36 changes: 20 additions & 16 deletions openapi/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import (
func getParameterValue(param *openapi3.Parameter) string {
if param.Schema != nil {
value := getSchemaValue(param.Schema.Value)
if param.Schema.Value.Type.Is("string") {
switch {
case param.Schema.Value.Type.Is("string"):
return value.(string)
} else if param.Schema.Value.Type.Is("number") {
case param.Schema.Value.Type.Is("number"):
return strconv.FormatFloat(value.(float64), 'f', -1, 64)
} else if param.Schema.Value.Type.Is("integer") {
case param.Schema.Value.Type.Is("integer"):
return strconv.Itoa(value.(int))
} else if param.Schema.Value.Type.Is("boolean") {
case param.Schema.Value.Type.Is("boolean"):
return strconv.FormatBool(value.(bool))
}
}
Expand All @@ -27,15 +28,16 @@ func getParameterValue(param *openapi3.Parameter) string {

func mapRequestBodyFakeValueToJSON(schema *openapi3.Schema, fakeValue interface{}) *bytes.Buffer {
jsonResponse := []byte("{}")
if schema.Type.Is("string") {
switch {
case schema.Type.Is("string"):
jsonResponse = []byte("\"" + fakeValue.(string) + "\"")
} else if schema.Type.Is("number") {
case schema.Type.Is("number"):
jsonResponse = []byte(strconv.FormatFloat(fakeValue.(float64), 'f', -1, 64))
} else if schema.Type.Is("integer") {
case schema.Type.Is("integer"):
jsonResponse = []byte(strconv.Itoa(fakeValue.(int)))
} else if schema.Type.Is("boolean") {
case schema.Type.Is("boolean"):
jsonResponse = []byte(strconv.FormatBool(fakeValue.(bool)))
} else if schema.Type.Is("array") {
case schema.Type.Is("array"):
jsonResponse = []byte("[")
for i, value := range fakeValue.([]interface{}) {
if i > 0 {
Expand All @@ -44,7 +46,7 @@ func mapRequestBodyFakeValueToJSON(schema *openapi3.Schema, fakeValue interface{
jsonResponse = append(jsonResponse, mapRequestBodyFakeValueToJSON(schema.Items.Value, value).Bytes()...)
}
jsonResponse = append(jsonResponse, ']')
} else if schema.Type.Is("object") {
case schema.Type.Is("object"):
jsonResponse = []byte("{")
i := 0
for key, value := range fakeValue.(map[string]interface{}) {
Expand All @@ -57,7 +59,6 @@ func mapRequestBodyFakeValueToJSON(schema *openapi3.Schema, fakeValue interface{
}
jsonResponse = append(jsonResponse, '}')
}

return bytes.NewBuffer(jsonResponse)
}

Expand All @@ -69,6 +70,8 @@ func getRequestBodyValue(requestBody *openapi3.RequestBody) (*bytes.Buffer, stri
switch mediaType {
case "application/json":
return mapRequestBodyFakeValueToJSON(mediaTypeValue.Schema.Value, body), "application/json"
default:
return bytes.NewBuffer([]byte(body.(string))), mediaType
}
}
}
Expand All @@ -85,19 +88,20 @@ func getSchemaValue(schema *openapi3.Schema) interface{} {
}

// if there is no example generate random param
if schema.Type.Is("number") || schema.Type.Is("integer") {
switch {
case schema.Type.Is("number") || schema.Type.Is("integer"):
return gofakeit.Number(0, 10)
} else if schema.Type.Is("boolean") {
case schema.Type.Is("boolean"):
return gofakeit.Bool()
} else if schema.Type.Is("array") {
case schema.Type.Is("array"):
return []interface{}{getSchemaValue(schema.Items.Value)}
} else if schema.Type.Is("object") {
case schema.Type.Is("object"):
object := map[string]interface{}{}
for key, value := range schema.Properties {
object[key] = getSchemaValue(value.Value)
}
return object
} else if schema.Type.Is("string") {
case schema.Type.Is("string"):
switch schema.Format {
case "date":
return gofakeit.Date().Format("2006-01-02")
Expand Down
Loading

0 comments on commit d48e9d9

Please sign in to comment.