From 0f128099b4b7dd7d04d43dcdcf5426fc6229a15c Mon Sep 17 00:00:00 2001 From: nathanmartinszup <63246935+nathanmartinszup@users.noreply.github.com> Date: Mon, 17 Jan 2022 09:42:40 -0300 Subject: [PATCH] engine:refactor - improving engine code and performance (#60) This commit contains a complete engine refactoring and includes some breaking changes. The use of the engine has been simplified to just one function called Run, this function will receive a context, project path that must be analyzed and a slice of rules. These rules are defined by a generic interface and each one have your own implementation, that will make it easy to add other types of analysis in the future, such as semantic. Various performance and code improvements have also been made, which dramatically improved code quality and analysis time. Signed-off-by: Nathan Martins --- .github/CODEOWNERS | 2 +- .golangci.yml | 30 +- Makefile | 42 +- copyright.txt | 2 +- engine.go | 232 ++++++----- engine_test.go | 128 ++++-- go.mod | 5 +- go.sum | 296 +------------- location.go | 29 -- logger.go | 1 + platforms/android/AndroidManifest.2.xml | 49 --- platforms/android/AndroidManifest.xml | 49 --- platforms/android/manifest.go | 158 -------- platforms/android/manifest_test.go | 131 ------- platforms/finding.go | 39 -- platforms/rule.go | 51 --- pool/pool.go | 53 +++ rule.go | 18 +- text/file.go | 253 ++++-------- text/file_test.go | 494 ++++++++---------------- text/reader.go | 50 --- text/reader_test.go | 88 ----- text/reader_win.go | 76 ---- text/reader_win_test.go | 38 -- text/rule.go | 209 +++++++++- text/rule_test.go | 171 ++++++++ text/unit.go | 184 --------- text/unit_test.go | 392 ------------------- 28 files changed, 915 insertions(+), 2355 deletions(-) delete mode 100644 location.go delete mode 100644 platforms/android/AndroidManifest.2.xml delete mode 100644 platforms/android/AndroidManifest.xml delete mode 100644 platforms/android/manifest.go delete mode 100644 platforms/android/manifest_test.go delete mode 100644 platforms/finding.go delete mode 100644 platforms/rule.go create mode 100644 pool/pool.go delete mode 100644 text/reader.go delete mode 100644 text/reader_test.go delete mode 100644 text/reader_win.go delete mode 100644 text/reader_win_test.go create mode 100644 text/rule_test.go delete mode 100644 text/unit.go delete mode 100644 text/unit_test.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f8fad06..059dda3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # GitHub code owners # See https://github.com/blog/2392-introducing-code-owners -* @wiliansilvazup @nathannascimentozup @igorreiszup @lucasbrunozup @nathanmartinszup +* @wiliansilvazup @matheusalcantarazup @lucasbrunozup @nathanmartinszup @iancardosozup diff --git a/.golangci.yml b/.golangci.yml index 3a5001d..8e1ba57 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - linters-settings: depguard: list-type: blacklist @@ -46,8 +45,6 @@ linters-settings: min-complexity: 5 goimports: local-prefixes: github.com/ZupIT/horusec-engine - golint: - min-confidence: 0 gomnd: settings: mnd: @@ -71,7 +68,7 @@ linters-settings: nolintlint: allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) allow-unused: false # report any unused nolint directives - require-explanation: false # don't require an explanation for nolint directives + require-explanation: true # don't require an explanation for nolint directives require-specific: false # don't require nolint directives to be specific about which linter is being skipped linters: @@ -94,7 +91,6 @@ linters: - gocyclo - gofmt - goimports - - golint - gomnd - goprintffuncname - gosec @@ -116,22 +112,26 @@ linters: - unused - varcheck - whitespace + - gci + - gofumpt + - testpackage + - wsl + - nlreturn + - nestif + - gocognit + - errorlint + - revive # don't enable: # - asciicheck # - scopelint # - gochecknoglobals - # - gocognit # - godot # - godox - # - goerr113 # - interfacer # - maligned - # - nestif # - prealloc - # - testpackage - # - revive - # - wsl + # - goerr113 issues: exclude-rules: @@ -140,11 +140,13 @@ exclude-rules: source: "^// " run: + skip-dirs-use-default: true skip-dirs: - vendor/ - - text/examples/ - - tmp + - tmp/ - e2e/ + - examples/ skip-files: - .*_test.go - - .*_mock.go \ No newline at end of file + - .*_mock.go + - ".*tmp.*" diff --git a/Makefile b/Makefile index 28a5ebc..bd259cc 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,18 @@ GO ?= go GOFMT ?= gofmt -GO_FILES ?= $$(find . -name '*.go' | grep -v vendor) -GOLANG_CI_LINT ?= ./bin/golangci-lint +GO_FILES ?= $$(find . -name '*.go' | grep -v vendor | grep -v /examples/) +GOLANG_CI_LINT ?= golangci-lint GO_IMPORTS ?= goimports GO_IMPORTS_LOCAL ?= github.com/ZupIT/horusec-engine HORUSEC ?= horusec +GO_FUMPT ?= gofumpt +GO_GCI ?= gci ADDLICENSE ?= addlicense GO_LIST_TO_TEST ?= $$(go list ./... | grep -v /text/examples/) -fmt: - $(GOFMT) -w $(GO_FILES) - lint: - ifeq ($(wildcard $(GOLANG_CI_LINT)), $(GOLANG_CI_LINT)) - $(GOLANG_CI_LINT) run -v --timeout=5m -c .golangci.yml ./... - else - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s latest - $(GOLANG_CI_LINT) run -v --timeout=5m -c .golangci.yml ./... - endif + $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + $(GOLANG_CI_LINT) run -v --timeout=5m -c .golangci.yml ./... coverage: curl -fsSL https://raw.githubusercontent.com/ZupIT/horusec-devkit/main/scripts/coverage.sh | bash -s 66.3 . @@ -26,13 +21,16 @@ test: $(GO) clean -testcache $(GO) test -v $(GO_LIST_TO_TEST) -race -timeout=5m -parallel=1 -failfast -short -fix-imports: - ifeq (, $(shell which $(GO_IMPORTS))) - $(GO) get -u golang.org/x/tools/cmd/goimports - $(GO_IMPORTS) -local $(GO_IMPORTS_LOCAL) -w $(GO_FILES) - else - $(GO_IMPORTS) -local $(GO_IMPORTS_LOCAL) -w $(GO_FILES) - endif +format: install-format-dependencies + $(GOFMT) -s -l -w $(GO_FILES) + $(GO_IMPORTS) -w -local $(GO_IMPORTS_LOCAL) $(GO_FILES) + $(GO_FUMPT) -l -w $(GO_FILES) + $(GO_GCI) -w -local $(GO_IMPORTS_LOCAL) $(GO_FILES) + +install-format-dependencies: + $(GO) install golang.org/x/tools/cmd/goimports@latest + $(GO) install mvdan.cc/gofumpt@latest + $(GO) install github.com/daixiang0/gci@latest security: ifeq (, $(shell which $(HORUSEC))) @@ -42,12 +40,12 @@ security: $(HORUSEC) start -p="./" -e="true" endif -pipeline: fmt fix-imports lint test coverage security - license: - $(GO) get -u github.com/google/addlicense + $(GO) install github.com/google/addlicense@latest @$(ADDLICENSE) -check -f ./copyright.txt $(shell find -regex '.*\.\(go\|js\|ts\|yml\|yaml\|sh\|dockerfile\)') license-fix: - $(GO) get -u github.com/google/addlicense + $(GO) install github.com/google/addlicense@latest @$(ADDLICENSE) -f ./copyright.txt $(shell find -regex '.*\.\(go\|js\|ts\|yml\|yaml\|sh\|dockerfile\)') + +pipeline: format license-fix lint test coverage security diff --git a/copyright.txt b/copyright.txt index 9d8cec3..68a398e 100644 --- a/copyright.txt +++ b/copyright.txt @@ -1,4 +1,4 @@ -Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +Copyright 2022 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/engine.go b/engine.go index 63b1168..ca8e7cb 100644 --- a/engine.go +++ b/engine.go @@ -15,20 +15,22 @@ package engine import ( - "encoding/json" - "fmt" - "math" - "os" + "context" + "io/fs" + "path/filepath" + "strings" + "sync" - "github.com/ZupIT/horusec-devkit/pkg/utils/logger" - loggerEnums "github.com/ZupIT/horusec-devkit/pkg/utils/logger/enums" + "golang.org/x/sync/errgroup" + + "github.com/ZupIT/horusec-engine/pool" ) -type Unit interface { - Type() UnitType - Eval(Rule) []Finding -} +// AcceptAnyExtension can be passed as extensions argument in NewEngine to accept any extension +const AcceptAnyExtension string = "*" +// Finding represents a possible vulnerability found by the engine, it contains all information necessary to detect and +// correct the vulnerability type Finding struct { ID string Name string @@ -39,125 +41,141 @@ type Finding struct { SourceLocation Location } -func Run(document []Unit, rules []Rule) (documentFindings []Finding) { - numberOfUnits := (len(document)) * (len(rules)) - if numberOfUnits == 0 { - return []Finding{} - } - - return executeRunByNumberOfUnits(numberOfUnits, document, rules) +// Location represents the location of the vulnerability in a file +type Location struct { + Filename string + Line int + Column int } -func RunOutputInJSON(document []Unit, rules []Rule, jsonFilePath string) error { - report := Run(document, rules) - bytesToWrite, err := json.MarshalIndent(report, "", " ") - if err != nil { - return err - } - outputFile, err := createOutputFile(jsonFilePath) - defer func() { - _ = outputFile.Close() - }() - if err != nil { - return err - } - return writeInOutputFile(outputFile, bytesToWrite) +// Engine contains all the engine necessary data +type Engine struct { + poolSize int + extensions []string } -func RunMaxUnitsByAnalysis(document []Unit, rules []Rule, maxUnitPerAnalysis int) (documentFindings []Finding) { - listDocuments := breakTextUnitsIntoLimitOfUnit(document, maxUnitPerAnalysis) - for key, units := range listDocuments { - logger.LogDebugWithLevel(fmt.Sprintf("Start run analysis %v/%v", key, len(listDocuments)), loggerEnums.DebugLevel) - documentFindings = append(documentFindings, Run(units, rules)...) +// NewEngine creates a new engine instance with all necessary data. +// extensions argument represents which extension the engine should apply the rules +// poolSize represents the number of go routines to open (Default is 10) +func NewEngine(poolSize int, extensions ...string) *Engine { + return &Engine{ + poolSize: poolSize, + extensions: extensions, } - return documentFindings } -func breakTextUnitsIntoLimitOfUnit(allUnits []Unit, maxUnitsPerAnalysis int) (units [][]Unit) { - units = [][]Unit{} - startIndex := 0 - endIndex := maxUnitsPerAnalysis - for i := 0; i < getTotalTextUnitsToRunByAnalysis(allUnits, maxUnitsPerAnalysis); i++ { - units = append(units, []Unit{}) - units = toBreakUnitsAddUnitAndUpdateStartEndIndex(allUnits, units, startIndex, endIndex, i) - startIndex = endIndex + 1 - endIndex += maxUnitsPerAnalysis - } - return units -} +// Run walks through projectPath and runs the method Rule.Run in a pool of goroutines +// if an error is found when executes Rule.Run method it cancels current running go routines and return +// valid findings and the error +// nolint:funlen,gocyclo // necessary complexity, breaking this function will lead to an even more complex code +func (e *Engine) Run(ctx context.Context, projectPath string, rules ...Rule) ([]Finding, error) { + var findings []Finding -func getTotalTextUnitsToRunByAnalysis(textUnits []Unit, maxUnitsPerAnalysis int) int { - totalTextUnits := len(textUnits) - if totalTextUnits <= maxUnitsPerAnalysis { - return 1 + paths, err := e.getValidFilePaths(projectPath) + if err != nil { + return nil, err } - totalUnitsToRun := float64(totalTextUnits / maxUnitsPerAnalysis) - // nolint:staticcheck // is necessary usage pointless in math.ceil - return int(math.Ceil(totalUnitsToRun)) -} -func toBreakUnitsAddUnitAndUpdateStartEndIndex( - allUnits []Unit, unitsToAppend [][]Unit, startIndex, endIndex, i int) [][]Unit { - if len(allUnits[startIndex:]) <= endIndex { - for k := range allUnits[startIndex:] { - unitsToAppend[i] = append(unitsToAppend[i], allUnits[k]) - } - } else { - for k := range allUnits[startIndex:endIndex] { - unitsToAppend[i] = append(unitsToAppend[i], allUnits[k]) - } - } - return unitsToAppend -} + mutex := new(sync.Mutex) + wg := sync.WaitGroup{} -func writeInOutputFile(outputFile *os.File, bytesToWrite []byte) error { - bytesWritten, err := outputFile.Write(bytesToWrite) + workerPool, err := pool.NewPool(e.poolSize) if err != nil { - return err + return nil, err } - if bytesWritten != len(bytesToWrite) { - return fmt.Errorf("bytes written and length of bytes to write is not equal: %v", map[string]interface{}{ - "bytesWritten": bytesWritten, - "bytesToWrite": string(bytesToWrite), + + defer workerPool.Release() + + group, _ := errgroup.WithContext(ctx) + + wg.Add(len(paths)) + + for _, path := range paths { + pathCopy := path + + errSubmit := workerPool.Submit(func() { + group.Go(func() error { + defer wg.Done() + + newFindings, errRunRule := e.runRule(rules, pathCopy) + if errRunRule != nil { + return errRunRule + } + + mutex.Lock() + findings = append(findings, newFindings...) + mutex.Unlock() + + return errRunRule + }) }) + if errSubmit != nil { + return nil, errSubmit + } } - return nil + + wg.Wait() + err = group.Wait() + + return findings, err } -//nolint:gomnd // improving in the feature -func createOutputFile(jsonFilePath string) (*os.File, error) { - if _, err := os.Create(jsonFilePath); err != nil { - return nil, err - } - outputFile, err := os.OpenFile(jsonFilePath, os.O_CREATE|os.O_WRONLY, 0600) - if err != nil { - return nil, err +func (e *Engine) runRule(rules []Rule, pathCopy string) ([]Finding, error) { + var findings []Finding + + for _, rule := range rules { + f, err := rule.Run(pathCopy) + if err != nil { + return nil, err + } + + findings = append(findings, f...) } - return outputFile, outputFile.Truncate(0) + + return findings, nil } -func executeRunByNumberOfUnits(numberOfUnits int, document []Unit, rules []Rule) (documentFindings []Finding) { - documentFindingsChannel := make(chan []Finding, numberOfUnits) - for _, documentUnit := range document { - localDocumentUnit := documentUnit - go execRulesInDocumentUnit(rules, localDocumentUnit, documentFindingsChannel) - } - for i := 1; i <= numberOfUnits; i++ { - unitFindings := <-documentFindingsChannel - documentFindings = append(documentFindings, unitFindings...) - } - close(documentFindingsChannel) - return documentFindings +// getValidFilePaths this function will walk the project directory and will look for files that match the extensions +// informed during the initialization of the engine and return a slice with it. +// Directories, sys links and files with extensions that are not in Engine.extensions struct wil be ignored +func (e *Engine) getValidFilePaths(projectPath string) ([]string, error) { + var validPaths []string + + err := filepath.WalkDir(projectPath, func(path string, entry fs.DirEntry, err error) error { + if err != nil || e.isInvalidFilePath(path, entry) { + return err + } + + validPaths = append(validPaths, path) + + return nil + }) + + return validPaths, err } -func execRulesInDocumentUnit(rules []Rule, documentUnit Unit, findings chan<- []Finding) { - for _, rule := range rules { - localRule := rule - if localRule.IsFor(documentUnit.Type()) { - go func() { - ruleFindings := documentUnit.Eval(localRule) - findings <- ruleFindings - }() +// isInvalidFilePath contains a list of validations to check if a path needs to be analyzed. It will ignore directories, +// sysLinks, extensions that don't match the necessary ones, and .git files +func (e *Engine) isInvalidFilePath(path string, entry fs.DirEntry) bool { + return entry.IsDir() || + entry.Type() == fs.ModeSymlink || + e.isInvalidExtension(path) || + e.isFileFromGitFolder(path) +} + +// isInvalidExtension verify if the filepath contains a valid file extension. +// The valid extensions are the ones that should be analyzed, and are passed during the initialization of the engine +func (e *Engine) isInvalidExtension(path string) bool { + for _, ext := range e.extensions { + if ext == filepath.Ext(path) || ext == AcceptAnyExtension { + return false } } + + return true +} + +// isFileFromGitFolder check if a file is in a .git folder +func (e *Engine) isFileFromGitFolder(path string) bool { + return strings.Contains(path, ".git") } diff --git a/engine_test.go b/engine_test.go index db65a4a..3cca464 100644 --- a/engine_test.go +++ b/engine_test.go @@ -15,53 +15,111 @@ package engine import ( + "context" + "errors" + "path/filepath" "testing" -) - -var TestUnitType UnitType = 999 - -type TestRule struct{} - -func (rule TestRule) IsFor(unitType UnitType) bool { - return TestUnitType == unitType -} -type TestUnit struct{} + "github.com/stretchr/testify/assert" +) -func (unit TestUnit) Type() UnitType { - return TestUnitType +type ruleMock struct { + findings []Finding + err error } -func (unit TestUnit) Eval(rule Rule) []Finding { - return []Finding{ - Finding{ - ID: "1", - }, +func newRuleMock(findings []Finding, err error) *ruleMock { + return &ruleMock{ + findings: findings, + err: err, } } -func TestRunWithTextUnits(t *testing.T) { - testProgram := []Unit{TestUnit{}} - rules := []Rule{TestRule{}} - - findings := Run(testProgram, rules) - - if len(findings) < 1 || len(findings) > 1 { - t.Fatal("Should find only 1 finding") - } +// Run will return a total of findings depending on total of file paths found in informed project path and total of +// findings passed to the mock (ruleMock.findings * file paths) +func (r *ruleMock) Run(_ string) ([]Finding, error) { + return r.findings, r.err } -func TestRunWith1000Units(t *testing.T) { - rules := []Rule{TestRule{}, TestRule{}, TestRule{}} - testProgram := []Unit{} - - for i := 0; i < 1000; i++ { - testProgram = append(testProgram, TestUnit{}) +func TestEngineRun(t *testing.T) { + testcases := []struct { + name string + projectPath string + extensions []string + rules Rule + err bool + expectedFindings int + }{ + { + name: "Should run without errors and return 225 findings", + projectPath: filepath.Join("text", "examples"), + extensions: []string{AcceptAnyExtension}, + rules: newRuleMock([]Finding{{}}, nil), + expectedFindings: 225, + err: false, + }, + { + name: "Should run without errors and return 24 findings", + projectPath: filepath.Join("text", "examples"), + extensions: []string{".ex"}, + rules: newRuleMock([]Finding{{}}, nil), + expectedFindings: 24, + err: false, + }, + { + name: "Should run without errors and return 3 findings", + projectPath: filepath.Join("text", "examples"), + extensions: []string{".py"}, + rules: newRuleMock([]Finding{{}}, nil), + expectedFindings: 3, + err: false, + }, + { + name: "Should run without errors and return 4 findings", + projectPath: filepath.Join("text", "examples"), + extensions: []string{".go"}, + rules: newRuleMock([]Finding{{}}, nil), + expectedFindings: 4, + err: false, + }, + { + name: "Should run without errors and return 0 findings", + projectPath: filepath.Join("text", "examples"), + extensions: []string{".invalidExt"}, + rules: newRuleMock([]Finding{{}}, nil), + expectedFindings: 0, + err: false, + }, + { + name: "Should return error when invalid project path", + projectPath: "invalidPath", + extensions: []string{AcceptAnyExtension}, + rules: newRuleMock(nil, nil), + expectedFindings: 0, + err: true, + }, + { + name: "Should return error when failed to run rule", + extensions: []string{AcceptAnyExtension}, + expectedFindings: 0, + rules: newRuleMock(nil, errors.New("test error")), + projectPath: filepath.Join("text", "examples"), + err: true, + }, } - findings := Run(testProgram, rules) + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + engine := NewEngine(0, testcase.extensions...) + + findings, err := engine.Run(context.Background(), testcase.projectPath, testcase.rules) + if testcase.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } - if len(findings) != 3000 { - t.Fatal("Should find only 3000 finding") + assert.Len(t, findings, testcase.expectedFindings) + }) } } diff --git a/go.mod b/go.mod index 7ebefd9..f5d499a 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,7 @@ go 1.14 require ( github.com/ZupIT/horusec-devkit v1.0.21 - github.com/antchfx/xmlquery v1.3.9 - github.com/antchfx/xpath v1.2.0 + github.com/panjf2000/ants/v2 v2.4.7 github.com/stretchr/testify v1.7.0 - golang.org/x/text v0.3.7 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ) diff --git a/go.sum b/go.sum index aafed61..a9012b5 100644 --- a/go.sum +++ b/go.sum @@ -21,7 +21,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -35,54 +34,26 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/ZupIT/horusec-devkit v1.0.17 h1:j4KtyP3bV7eAWNZtk/2ZB9TIZYaD7QyUv0zRDPuKWiA= -github.com/ZupIT/horusec-devkit v1.0.17/go.mod h1:wTsXrXTD1YrChTQEng8EvVg+zL9nMUIQkhUG85sQwuQ= -github.com/ZupIT/horusec-devkit v1.0.19 h1:eQNzst0a91YkAzSWy+1A/brBR9Lon2dMmzs0vZ3dUzQ= -github.com/ZupIT/horusec-devkit v1.0.19/go.mod h1:8rEUFNoFOGeAIG1unUfaF5qP6agHPnf9WsMtGfQR/iU= github.com/ZupIT/horusec-devkit v1.0.21 h1:vAY0/DV+EMdfSae6cu8lF0UpGrJe1uuMW3H/TDznvdE= github.com/ZupIT/horusec-devkit v1.0.21/go.mod h1:ZNpTXWcN0tG7jHokH12Zi94Y2iiV1qxslElvfSD/kDE= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antchfx/xmlquery v1.3.7 h1:0hc7OU2rFIu8MMKT5kknruaTKsoCybkUaUFMnB1LOO4= -github.com/antchfx/xmlquery v1.3.7/go.mod h1:wojC/BxjEkjJt6dPiAqUzoXO5nIMWtxHS8PD8TmN4ks= -github.com/antchfx/xmlquery v1.3.9 h1:Y+zyMdiUZ4fasTQTkDb3DflOXP7+obcYEh80SISBmnQ= -github.com/antchfx/xmlquery v1.3.9/go.mod h1:wojC/BxjEkjJt6dPiAqUzoXO5nIMWtxHS8PD8TmN4ks= -github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8= -github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/auth0/go-jwt-middleware v1.0.1/go.mod h1:YSeUX3z6+TF2H+7padiEqNJ73Zy9vXW72U//IgN0BIM= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -90,7 +61,6 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -100,32 +70,14 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -133,15 +85,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -149,7 +95,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -170,21 +115,13 @@ github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5H github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -209,7 +146,6 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -238,70 +174,28 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20210420193930-a4630ec28c79/go.mod h1:Opf9rtYVq0eTyX+aRVmRO9hE8ERAozcdrBxWG9Q6mkQ= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -313,48 +207,30 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -362,7 +238,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -377,136 +252,61 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/migueleliasweb/go-github-mock v0.0.5/go.mod h1:gTpcHVcrBxK35OOQP3aGrgQypxvEoFTvtR0VGaEs2VM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/panjf2000/ants/v2 v2.4.7 h1:MZnw2JRyTJxFwtaMtUJcwE618wKD04POWk2gwwP4E2M= +github.com/panjf2000/ants/v2 v2.4.7/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -516,24 +316,9 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -545,31 +330,18 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/http-swagger v1.1.1/go.mod h1:cKIcshBU9yEAnfWv6ZzVKSsEf8h5ozxB8/zHQWyOQ/8= github.com/swaggo/http-swagger v1.1.2/go.mod h1:mX5nhypDmoSt4iw2mc5aKXxRFvp1CLLcCiog2B9M+Ro= github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo= github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -588,23 +360,17 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -629,7 +395,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -638,16 +403,10 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -673,7 +432,6 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -683,11 +441,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -705,15 +459,11 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -726,12 +476,9 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -755,15 +502,12 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -774,14 +518,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -802,7 +542,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -832,14 +571,12 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -857,7 +594,6 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -869,7 +605,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -895,17 +630,11 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -917,7 +646,6 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -938,37 +666,23 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= -gorm.io/driver/postgres v1.1.2/go.mod h1:/AGV0zvqF3mt9ZtzLzQmXWQ/5vr+1V1TyHZGZVjzmwI= gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs= -gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.11/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.16/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -979,5 +693,3 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/location.go b/location.go deleted file mode 100644 index 26ce330..0000000 --- a/location.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package engine - -import ( - "fmt" -) - -type Location struct { - Filename string - Line int - Column int -} - -func (location Location) String() string { - return fmt.Sprintf("Name: %s Location: %d:%d", location.Filename, location.Line, location.Column) -} diff --git a/logger.go b/logger.go index e97df4a..7ec3aa3 100644 --- a/logger.go +++ b/logger.go @@ -16,6 +16,7 @@ package engine import "github.com/ZupIT/horusec-devkit/pkg/utils/logger" +// SetLogLevel used to set the engine log level func SetLogLevel(level string) { logger.SetLogLevel(level) } diff --git a/platforms/android/AndroidManifest.2.xml b/platforms/android/AndroidManifest.2.xml deleted file mode 100644 index 78aa4b7..0000000 --- a/platforms/android/AndroidManifest.2.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platforms/android/AndroidManifest.xml b/platforms/android/AndroidManifest.xml deleted file mode 100644 index 76c967b..0000000 --- a/platforms/android/AndroidManifest.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platforms/android/manifest.go b/platforms/android/manifest.go deleted file mode 100644 index f60da38..0000000 --- a/platforms/android/manifest.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package android - -import ( - "bytes" - - "github.com/antchfx/xmlquery" - - engine "github.com/ZupIT/horusec-engine" - "github.com/ZupIT/horusec-engine/platforms" -) - -// Permission holds data about all the declared permissions in an AndroidManifest.xml file -type Permission struct { - Name string `xml:"name,attr"` - Required string `xml:"required,attr"` -} - -// SDKInfo holds information about the target and compilation SDK of the given App -type SDKInfo struct { - MinimumSDKVersion string `xml:"minSdkVersion,attr"` - TargetSDKVersion string `xml:"targetSdkVersion,attr"` - MaximumSDKVersion string `xml:"maxSdkVersion,attr"` -} - -// IntentAction holds data about the declared Actions that can be performed in given Activity. -type IntentAction struct { - Name string `xml:"name,attr"` -} - -// IntentCategory is the Activity's category. -type IntentCategory struct { - Name string `xml:"name,attr"` -} - -// IntentFilter holds imformational data about the `intention-filter` tag for the given Activity. -type IntentFilter struct { - Categories IntentCategory `xml:"category"` - Actions []IntentAction `xml:"action"` -} - -// Activity represents an Activity entry in the manifest file -type Activity struct { - Name string `xml:"name,attr"` - IntentFilter IntentFilter `xml:"intent-filter"` -} - -// BroadcastReceiver represents a broadcast receiver entry in the manifest file -type BroadcastReceiver struct { - Name string `xml:"name,attr"` - Enabled string `xml:"enabled,attr"` - IsExported string `xml:"exported,attr"` - Permission string `xml:"permission,attr"` -} - -// Service represents a Service entry in the manifest file -type Service struct { - Name string `xml:"name,attr"` - IsExported string `xml:"exported,attr"` - Permission string `xml:"permission,attr"` -} - -// ApplicationInfo holds all the data about the application components of the app -type ApplicationInfo struct { - Name string `xml:"name,attr"` - AllowADBBackup string `xml:"allowBackup,attr"` - Activities []Activity `xml:"activity"` - BroadcastReceivers []BroadcastReceiver `xml:"receiver"` - Services []Service `xml:"service"` -} - -// Manifest is a marshaled version of all the data in the AndroidManifest.xml file -type Manifest struct { - PackageName string `xml:"package,attr"` - SDKInfo SDKInfo `xml:"uses-sdk"` - Application ApplicationInfo `xml:"application"` - Permissions []Permission `xml:"uses-permission"` -} - -type ManifestUnit struct { - Document *xmlquery.Node -} - -func (unit ManifestUnit) Type() engine.UnitType { - return engine.StructuredDataUnit -} - -// nolint // Complex method for pass refactor now TODO: Refactor this method in the future to clean code -func (unit ManifestUnit) Eval(rule engine.Rule) (unitFindings []engine.Finding) { - if structuredDataRule, ok := rule.(platforms.StructuredDataRule); ok { - switch structuredDataRule.Type { - case platforms.RegularMatch: - for _, expression := range structuredDataRule.Expressions { - exprResult := xmlquery.QuerySelectorAll(unit.Document, expression) - - if len(exprResult) < 1 { - return - } - - for _, finding := range exprResult { - unitFindings = append( - unitFindings, - platforms.PopulateFindingWithRuleMetadata( - structuredDataRule, - "AndroidManifest.xml", finding.OutputXML(true), 0, 0), - ) - } - } - case platforms.NotMatch: - for _, expression := range structuredDataRule.Expressions { - exprResult := xmlquery.QuerySelectorAll(unit.Document, expression) - - if len(exprResult) > 0 { - return - } - - unitFindings = append( - unitFindings, - platforms.PopulateFindingWithRuleMetadata(structuredDataRule, - "AndroidManifest.xml", "", 0, 0), - ) - } - default: - return unitFindings - } - } - - return unitFindings -} - -func NewManifestUnit(content []byte) (unit *ManifestUnit, err error) { - manifestRawDataReader := bytes.NewReader(content) - - formattedDocument, err := xmlquery.Parse(manifestRawDataReader) - - if err != nil { - return unit, err - } - - unit = &ManifestUnit{ - Document: formattedDocument, - } - - return unit, nil -} diff --git a/platforms/android/manifest_test.go b/platforms/android/manifest_test.go deleted file mode 100644 index f2d0ca9..0000000 --- a/platforms/android/manifest_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package android - -import ( - "os" - "testing" - - engine "github.com/ZupIT/horusec-engine" - "github.com/ZupIT/horusec-engine/platforms" -) - -func TestLoadingAManifestUnitWithValidManifestShouldWork(t *testing.T) { - androidManifest, err := os.ReadFile("AndroidManifest.xml") - - if err != nil { - t.Fatal(err) - } - - _, err = NewManifestUnit(androidManifest) - - if err != nil { - t.Fatal(err) - } -} - -func TestMatchRegularRuleWithValidManifestShouldWork(t *testing.T) { - androidManifest, err := os.ReadFile("AndroidManifest.xml") - - if err != nil { - t.Fatal(err) - } - - manifestUnit, err := NewManifestUnit(androidManifest) - - if err != nil { - t.Fatal(err) - } - - exportedRule := platforms.NewStructuredDataRule(platforms.RegularMatch, []string{`//manifest//application//activity[@android:exported='true']`}) - - findings := engine.Run([]engine.Unit{manifestUnit}, []engine.Rule{exportedRule}) - - if len(findings) <= 0 { - t.Fatal("Should have found something") - } -} - -func TestMatchNotRuleWithValidManifestShouldWork(t *testing.T) { - androidManifest, err := os.ReadFile("AndroidManifest.xml") - - if err != nil { - t.Fatal(err) - } - - manifestUnit, err := NewManifestUnit(androidManifest) - - if err != nil { - t.Fatal(err) - } - - exportedRule := platforms.NewStructuredDataRule(platforms.NotMatch, []string{`//manifest//application[@usesCleartextTraffic='true']`}) - exportedRule.Description = "Congratulations! You're not using the usesCleattextTraffic property on your applications!" - - findings := engine.Run([]engine.Unit{manifestUnit}, []engine.Rule{exportedRule}) - - if len(findings) <= 0 { - t.Fatal("Should have found something") - } -} - -func TestMatchNotRuleWithValidManifestShouldWorkFindingAnIssue(t *testing.T) { - androidManifest, err := os.ReadFile("AndroidManifest.2.xml") - - if err != nil { - t.Fatal(err) - } - - manifestUnit, err := NewManifestUnit(androidManifest) - - if err != nil { - t.Fatal(err) - } - - exportedRule := platforms.NewStructuredDataRule(platforms.NotMatch, []string{`//manifest//application[@android:usesCleartextTraffic='true']`}) - exportedRule.Description = "Congratulations! You're not using the usesCleattextTraffic property on your applications!" - - findings := engine.Run([]engine.Unit{manifestUnit}, []engine.Rule{exportedRule}) - - if len(findings) > 0 { - t.Fatal("Should not have found something") - } -} - -func TestCustomXPathExpressionsHandlingWithValidManifestShouldWork(t *testing.T) { - androidManifest, err := os.ReadFile("AndroidManifest.xml") - - if err != nil { - t.Fatal(err) - } - - manifestUnit, err := NewManifestUnit(androidManifest) - - if err != nil { - t.Fatal(err) - } - - exportedRule := platforms.NewStructuredDataRule(platforms.RegularMatch, []string{`//manifest//application//activity[@android:name[ - contains( - translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'), - 'smali') - ]]`}) - - findings := engine.Run([]engine.Unit{manifestUnit}, []engine.Rule{exportedRule}) - - if len(findings) <= 0 { - t.Fatal("Should have found something") - } -} diff --git a/platforms/finding.go b/platforms/finding.go deleted file mode 100644 index f3bdc9d..0000000 --- a/platforms/finding.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package platforms - -import ( - engine "github.com/ZupIT/horusec-engine" -) - -// PopulateFindingWithRuleMetadata converts the engine.Metadata field inside the StructuredDataRule to a engine.Finding -// struct -//nolint // change to pointer -func PopulateFindingWithRuleMetadata( - ruleData StructuredDataRule, filename, codeSample string, line, column int) engine.Finding { - return engine.Finding{ - ID: ruleData.ID, - Name: ruleData.Name, - Severity: ruleData.Severity, - Confidence: ruleData.Confidence, - Description: ruleData.Description, - CodeSample: codeSample, - SourceLocation: engine.Location{ - Filename: filename, - Line: line, - Column: column, - }, - } -} diff --git a/platforms/rule.go b/platforms/rule.go deleted file mode 100644 index 078b4c0..0000000 --- a/platforms/rule.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package platforms - -import ( - "github.com/antchfx/xpath" - - engine "github.com/ZupIT/horusec-engine" -) - -type MatchType int - -const ( - RegularMatch MatchType = iota - NotMatch -) - -type StructuredDataRule struct { - engine.Metadata - Type MatchType - Expressions []*xpath.Expr -} - -//nolint // change to pointer -func (rule StructuredDataRule) IsFor(unitType engine.UnitType) bool { - return engine.StructuredDataUnit == unitType -} - -func NewStructuredDataRule(matchType MatchType, queryStrings []string) StructuredDataRule { - var exprs []*xpath.Expr - for _, query := range queryStrings { - exprs = append(exprs, xpath.MustCompile(query)) - } - - return StructuredDataRule{ - Type: matchType, - Expressions: exprs, - } -} diff --git a/pool/pool.go b/pool/pool.go new file mode 100644 index 0000000..64b47ec --- /dev/null +++ b/pool/pool.go @@ -0,0 +1,53 @@ +// Copyright 2022 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pool + +import ( + "time" + + "github.com/panjf2000/ants/v2" +) + +const ( + // DefaultAntsPoolSize sets up the capacity of worker pool, 256 * 1024. + DefaultAntsPoolSize = 10 + + // ExpiryDuration is the interval time to clean up those expired workers. + ExpiryDuration = 10 * time.Second +) + +// Pool is the alias of ants.Pool. +type Pool = ants.Pool + +// NewPool instantiates a new goroutine pool with poolSize argument or default pool size. +func NewPool(poolSize int) (*Pool, error) { + return ants.NewPool(getDefaultOrInformedPoolSize(poolSize), ants.WithOptions(getOptions())) +} + +// getDefaultOrInformedPoolSize returns informed pool size if greater than 0 or default pool size if 0 or lower +func getDefaultOrInformedPoolSize(poolSize int) int { + if poolSize > 0 { + return poolSize + } + + return DefaultAntsPoolSize +} + +// getOptions get ants goroutine pool options +func getOptions() ants.Options { + return ants.Options{ + ExpiryDuration: ExpiryDuration, + } +} diff --git a/rule.go b/rule.go index 489ad0f..d8c56fd 100644 --- a/rule.go +++ b/rule.go @@ -14,28 +14,16 @@ package engine -// UnitType defines which type of content, and therefore, which kind of rule -// is needed in order to extract information about the program we are analyzing -type UnitType int - -const ( - ProgramTextUnit UnitType = iota - StructuredDataUnit -) - // Rule defines a generic rule for any kind of analysis the engine have to execute type Rule interface { - IsFor(UnitType) bool // Indicates which kind of program unit this rules can be ran on + Run(path string) ([]Finding, error) } // Metadata holds information for the rule to match a useful advisory type Metadata struct { ID string Name string - CodeSample string Description string - - // Metadata levels - Severity string - Confidence string + Severity string + Confidence string } diff --git a/text/file.go b/text/file.go index 0485fc8..b6020a0 100644 --- a/text/file.go +++ b/text/file.go @@ -15,96 +15,68 @@ package text import ( - "bytes" - "fmt" - "os" "path/filepath" "regexp" "sort" "strings" - "time" - - "github.com/ZupIT/horusec-devkit/pkg/utils/logger" - loggerEnums "github.com/ZupIT/horusec-devkit/pkg/utils/logger/enums" ) -var ( - newlineFinder *regexp.Regexp = regexp.MustCompile("\x0a") +// regexNewLine regex representing the new line hexadecimal, equivalent of \n. +var regexNewLine = regexp.MustCompile("\x0a") + +// File represents a file to be analyzed +type File struct { + // AbsolutePath holds the complete path to the file (e.g. /home/user/myProject/router/handler.js) + AbsolutePath string + RelativePath string // RelativePath holds the raw path relative to the root folder of the project + Content []byte // Content holds all the file content + Name string // Name holds only the single name of the file (e.g. handler.js) + newlineIndexes [][]int // newlineIndexes holds information about where is the beginning and ending of each line + newlineEndingIndexes []int // newlineEndingIndexes represents the *start* index of each '\n' rune in the file +} + +// NewTextFile create a new text file with all necessary info filled +func NewTextFile(relativeFilePath string, content []byte) (*File, error) { + file := &File{ + RelativePath: relativeFilePath, + Content: content, + Name: filepath.Base(relativeFilePath), + newlineIndexes: regexNewLine.FindAllIndex(content, -1), + } - PEMagicBytes []byte = []byte{'\x4D', '\x5A'} // MZ - ELFMagicNumber []byte = []byte{'\x7F', '\x45', '\x4C', '\x46'} // .ELF -) + if err := file.setAbsFilePath(); err != nil { + return nil, err + } -const AcceptAllExtensions string = "**" + file.setNewlineEndingIndexes() -// binarySearch function uses this search algorithm to find the index of the matching element. -func binarySearch(searchIndex int, collection []int) (foundIndex int) { - foundIndex = sort.Search( - len(collection), - func(index int) bool { return collection[index] >= searchIndex }, - ) - return + return file, nil } -// TextFile represents a file to be analyzed -// nolint:golint // name is necessary for now called TextFile for not occurs breaking changes -type TextFile struct { - DisplayName string // Holds the raw path relative to the root folder of the project - Name string // Holds only the single name of the file (e.g. handler.js) - RawString string // Holds all the file content - - // Holds the complete path to the file, could be absolute or not (e.g. /home/user/myProject/router/handler.js) - PhysicalPath string - - // Indexes for internal file reference - // newlineIndexes holds information about where is the beginning and ending of each line in the file - newlineIndexes [][]int - // newlineEndingIndexes represents the *start* index of each '\n' rune in the file - newlineEndingIndexes []int -} +// setAbsFilePath verifies if the filepath is absolute and set, otherwise it will parse and then set +func (f *File) setAbsFilePath() error { + if filepath.IsAbs(f.RelativePath) { + f.AbsolutePath = f.RelativePath -func NewTextFile(relativeFilePath string, content []byte) (TextFile, error) { - formattedPhysicalPath, err := validateRelativeFilePath(relativeFilePath) - if err != nil { - return TextFile{}, err + return nil } - return createTextFileByPath(formattedPhysicalPath, relativeFilePath, content), nil -} - -func createTextFileByPath(formattedPhysicalPath, relativeFilePath string, content []byte) TextFile { - _, formattedFilename := filepath.Split(formattedPhysicalPath) - textfile := TextFile{ - PhysicalPath: formattedPhysicalPath, - RawString: string(content), + absolutePath, err := filepath.Abs(f.RelativePath) + f.AbsolutePath = absolutePath - // Display info - Name: formattedFilename, - DisplayName: relativeFilePath, - } - textfile.newlineIndexes = newlineFinder.FindAllIndex(content, -1) - - for _, newlineIndex := range textfile.newlineIndexes { - textfile.newlineEndingIndexes = append(textfile.newlineEndingIndexes, newlineIndex[0]) - } - return textfile + return err } -func validateRelativeFilePath(relativeFilePath string) (string, error) { - if !filepath.IsAbs(relativeFilePath) { - return filepath.Abs(relativeFilePath) +// setNewlineEndingIndexes for each new line index set the ending index +func (f *File) setNewlineEndingIndexes() { + for _, newlineIndex := range f.newlineIndexes { + f.newlineEndingIndexes = append(f.newlineEndingIndexes, newlineIndex[0]) } - - return relativeFilePath, nil -} - -//nolint // change to pointer -func (textfile TextFile) Content() string { - return textfile.RawString } -// nolint // refact to have a clean code -func (textfile TextFile) FindLineAndColumn(findingIndex int) (line, column int) { +// nolint:funlen,wsl // todo complex function need to be improved +// FindLineAndColumn get line and column using the beginning index of the example code +func (f *File) FindLineAndColumn(findingIndex int) (line, column int) { // findingIndex is the index of the beginning of the text we want to // locate inside the file @@ -114,15 +86,14 @@ func (textfile TextFile) FindLineAndColumn(findingIndex int) (line, column int) // so we search for where we would put the findingIndex in the array // using a binary search algorithm, because this will give us the exact // lines that the index is between. - lineIndex := binarySearch(findingIndex, textfile.newlineEndingIndexes) + lineIndex := f.binarySearch(findingIndex, f.newlineEndingIndexes) // Now with the right index found we have to get the previous \n // from the findingIndex, so it gets the right line - if lineIndex < len(textfile.newlineEndingIndexes) { + if lineIndex < len(f.newlineEndingIndexes) { // we add +1 here because we want the line to // reflect the "human" line count, not the indexed one in the slice line = lineIndex + 1 - endOfCurrentLine := lineIndex - 1 // If there is no previous line the finding is in the beginning @@ -132,137 +103,45 @@ func (textfile TextFile) FindLineAndColumn(findingIndex int) (line, column int) } // now we access the textual index in the slice to ge the column - endOfCurrentLineInTheFile := textfile.newlineEndingIndexes[endOfCurrentLine] + endOfCurrentLineInTheFile := f.newlineEndingIndexes[endOfCurrentLine] + if lineIndex == 0 { column = findingIndex } else { column = (findingIndex - 1) - endOfCurrentLineInTheFile } } - return line, column -} - -//nolint // change to pointer -func (textfile TextFile) ExtractSample(findingIndex int) string { - lineIndex := binarySearch(findingIndex, textfile.newlineEndingIndexes) - - if lineIndex < len(textfile.newlineEndingIndexes) { - endOfPreviousLine := 0 - if lineIndex > 0 { - endOfPreviousLine = textfile.newlineEndingIndexes[lineIndex-1] + 1 - } - endOfCurrentLine := textfile.newlineEndingIndexes[lineIndex] - lineContent := textfile.RawString[endOfPreviousLine:endOfCurrentLine] - - return strings.TrimSpace(lineContent) - } - - return "" + return line, column } -func ReadAndCreateTextFile(filename string) (TextFile, error) { - textFileContent, err := ReadTextFileUnix(filename) - if err != nil { - return TextFile{}, err - } - - textFileMagicBytes := textFileContent[:4] - if bytes.Equal(textFileMagicBytes, ELFMagicNumber) { - // Ignore Linux binaries - return TextFile{}, nil - } else if bytes.Equal(textFileContent[:2], PEMagicBytes) { - // Ignore Windows binaries - return TextFile{}, nil - } - - return NewTextFile(filename, textFileContent) -} +// binarySearch function uses this search algorithm to find the index of the matching element. +func (f *File) binarySearch(searchIndex int, collection []int) (foundIndex int) { + foundIndex = sort.Search( + len(collection), + func(index int) bool { return collection[index] >= searchIndex }, + ) -// The Param extensionAccept is an filter to check if you need get textUnit for file with this extesion -// Example: []string{".java"} -// If an item of slice contains is equal the "**" it's will accept all extensions -// Example: []string{"**"} -func LoadDirIntoSingleUnit(path string, extensionsAccept []string) (TextUnit, error) { - listTextUnit, err := loadDirIntoUnit(path, 0, extensionsAccept) - if err != nil { - return TextUnit{}, err - } - if len(listTextUnit) < 1 { - return TextUnit{}, nil - } - return listTextUnit[0], nil + return } -// The Param extensionAccept is an filter to check if you need get textUnit for file with this extesion -// Example: []string{".java"} -// If an item of slice contains is equal the "**" it's will accept all extensions -// Example: []string{"**"} -func LoadDirIntoMultiUnit(path string, maxFilesPerTextUnit int, extensionsAccept []string) ([]TextUnit, error) { - return loadDirIntoUnit(path, maxFilesPerTextUnit, extensionsAccept) -} +// nolint:funlen // todo complex function, needs to be improved +// ExtractSample search for the vulnerable code using the finding indexes +func (f *File) ExtractSample(findingIndex int) string { + lineIndex := f.binarySearch(findingIndex, f.newlineEndingIndexes) -func loadDirIntoUnit(path string, maxFilesPerTextUnit int, extensionsAccept []string) ([]TextUnit, error) { - filesToRun, err := getFilesPathIntoProjectPath(path, extensionsAccept) - if err != nil { - return []TextUnit{}, err - } - return getTextUnitsFromFilesPath(filesToRun, maxFilesPerTextUnit) -} + if lineIndex < len(f.newlineEndingIndexes) { + endOfPreviousLine := 0 -func getFilesPathIntoProjectPath(projectPath string, extensionsAccept []string) (filesToRun []string, err error) { - return filesToRun, filepath.Walk(projectPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - if checkIfEnableExtension(path, extensionsAccept) { - filesToRun = append(filesToRun, path) - } + if lineIndex > 0 { + endOfPreviousLine = f.newlineEndingIndexes[lineIndex-1] + 1 } - return nil - }) -} -//nolint // refactor to constant -func getTextUnitsFromFilesPath(filesToRun []string, maxFilesPerTextUnit int) (textUnits []TextUnit, err error) { - textUnits = []TextUnit{{}} - lastIndexToAdd := 0 - for k, currentFile := range filesToRun { - time.Sleep(15 * time.Millisecond) - currentTime := time.Now() - textUnits, lastIndexToAdd, err = readFileAndExtractTextUnit( - textUnits, lastIndexToAdd, maxFilesPerTextUnit, currentFile) - logger.LogTraceWithLevel(fmt.Sprintf( - "Read file in %v Microseconds. Total files read: %v/%v ", - time.Since(currentTime).Microseconds(), k, len(filesToRun)), loggerEnums.TraceLevel, currentFile) - if err != nil { - return []TextUnit{}, err - } - } - return textUnits, nil -} + endOfCurrentLine := f.newlineEndingIndexes[lineIndex] + lineContent := f.Content[endOfPreviousLine:endOfCurrentLine] -func readFileAndExtractTextUnit( - textUnits []TextUnit, lastIndexToAdd, maxFilesPerTextUnit int, currentFile string) ([]TextUnit, int, error) { - textFile, err := ReadAndCreateTextFile(currentFile) - if err != nil { - return []TextUnit{}, lastIndexToAdd, err - } - textUnits[lastIndexToAdd].Files = append(textUnits[lastIndexToAdd].Files, textFile) - if maxFilesPerTextUnit > 0 && len(textUnits[lastIndexToAdd].Files) >= maxFilesPerTextUnit { - textUnits = append(textUnits, TextUnit{}) - return textUnits, lastIndexToAdd + 1, nil + return strings.TrimSpace(string(lineContent)) } - return textUnits, lastIndexToAdd, nil -} -func checkIfEnableExtension(path string, extensionsAccept []string) bool { - ext := filepath.Ext(path) - for _, extAccept := range extensionsAccept { - if ext == extAccept || extAccept == AcceptAllExtensions { - return true - } - } - return false + return "" } diff --git a/text/file_test.go b/text/file_test.go index 89fc1f5..c721bfd 100644 --- a/text/file_test.go +++ b/text/file_test.go @@ -15,6 +15,7 @@ package text import ( + "errors" "path/filepath" "regexp" "testing" @@ -22,366 +23,185 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFindLineAndColumnWithAKotlinController(t *testing.T) { - var exampleKotlinController = `package org.jetbrains.kotlin.demo - -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestParam -import org.springframework.web.bind.annotation.RestController -import java.util.concurrent.atomic.AtomicLong - -@RestController -class GreetingController { - - val counter = AtomicLong() - - @GetMapping("/greeting") - fun greeting(@RequestParam(value = "name", defaultValue = "World") name: String) = - Greeting(counter.incrementAndGet(), "Hello, $name") - -} -` - - nameVariableLine := 14 - nameVariableColumn := 71 - - // So we lookup for something in the file - // in this case the 'name: String' variable - // and the method should return the correct line and column - // for where it is, in a human readable form. - nameStringExtractor := regexp.MustCompile(`name\:`) - - findingIndex := nameStringExtractor.FindStringIndex(exampleKotlinController) - - controllerTextFile, err := NewTextFile("example/controller.kt", []byte(exampleKotlinController)) - - if err != nil { - t.Error(err) - } - - line, column := controllerTextFile.FindLineAndColumn(findingIndex[0]) - - if line != nameVariableLine || column != nameVariableColumn { - t.Errorf( - "Failed to find the right line and column. Wanted: %d:%d. Found: %d:%d", - nameVariableLine, nameVariableColumn, - line, column, - ) - } -} - -func TestFindLineAndColumnWithAGoFile(t *testing.T) { - var exampleGoFile = `package version - -import ( - "github.com/ZupIT/horusec/development-kit/pkg/utils/logger" - "github.com/spf13/cobra" -) - -type IVersion interface { - CreateCobraCmd() *cobra.Command -} - -type Version struct { -} - -func NewVersionCommand() IVersion { - return &Version{} -} - -func (v *Version) CreateCobraCmd() *cobra.Command { - return &cobra.Command{ - Use: "version", - Short: "Actual version installed of the horusec", - Example: "horusec version", - RunE: func(cmd *cobra.Command, args []string) error { - logger.LogPrint(cmd.Short + " is: ") - return nil - }, - } -} -` - cmdShortVariableLine := 25 - cmdShortVariableColumn := 19 - - cmdShortExtractor := regexp.MustCompile(`cmd\.Short`) - - findingIndex := cmdShortExtractor.FindStringIndex(exampleGoFile) - - goTextFile, err := NewTextFile("example/cmd/version.go", []byte(exampleGoFile)) - - if err != nil { - t.Error(err) - } - - line, column := goTextFile.FindLineAndColumn(findingIndex[0]) - - if line != cmdShortVariableLine || column != cmdShortVariableColumn { - t.Errorf( - "Failed to find the right line and column. Wanted: %d:%d. Found: %d:%d", - cmdShortVariableLine, cmdShortVariableColumn, - line, column, - ) - } -} - -func TestExtractSampleWithAGoFile(t *testing.T) { - var exampleGoFile = `package version - -import ( - "github.com/ZupIT/horusec/development-kit/pkg/utils/logger" - "github.com/spf13/cobra" -) - -type IVersion interface { - CreateCobraCmd() *cobra.Command -} - -type Version struct { -} - -func NewVersionCommand() IVersion { - return &Version{} -} - -func (v *Version) CreateCobraCmd() *cobra.Command { - return &cobra.Command{ - Use: "version", - Short: "Actual version installed of the horusec", - Example: "horusec version", - RunE: func(cmd *cobra.Command, args []string) error { - logger.LogPrint(cmd.Short + " is: ") - return nil - }, - } -} -` - cmdShortExtractor := regexp.MustCompile(`cmd\.Short`) - - findingIndex := cmdShortExtractor.FindStringIndex(exampleGoFile) - - goTextFile, err := NewTextFile("example/cmd/version.go", []byte(exampleGoFile)) - - if err != nil { - t.Error(err) - } - - lineContent := goTextFile.ExtractSample(findingIndex[0]) - - if lineContent != `logger.LogPrint(cmd.Short + " is: ")` { - t.Fatalf("Failed to find the correct line content. Found: %s", lineContent) - } -} - -func TestFindLineAndColumnWithAJavascriptFile(t *testing.T) { - var exampleJsFile = `function die(msg) { alert(msg); return false; } - -function checkValue($form, selector, name, expected_value) { - var input = $form.find(selector)[0]; - if (!input) { return die('You seem to be missing a required input.'); } - if ($(input).attr('value').toLowerCase() !== expected_value.toLowerCase()) { - return die('You seem to be using the wrong value for ' + name + '.'); - } - return true; -} - -var allowed_actions = ['http://localhost:8000/csrf/gift-card', 'http://127.0.0.1:8000/csrf/gift-card']; -$(document).on('submit', 'form', function(e) { - var $form = $(this); - if (!$form.attr('action') || allowed_actions.indexOf($form.attr('action')) === -1) { - return die("Check your form action. It appears to be incorrect. You want the full URL to the giftcard form!"); - } - if (!$form.attr('method') || $form.attr('method').toUpperCase() != 'POST') { - return die("Check your form method. You should be POSTing."); - } - - // inputs should be either hidden or submit - var inputs = $form.find('input').toArray(); - for (var i in inputs) { - var type = $(inputs[i]).attr('type') || ''; - switch (type.toLowerCase()) { - case 'hidden': - case 'submit': - break; // all good - default: - return die("You appear to have inputs that are not hidden."); +const ( + sampleKotlin = ` + package org.jetbrains.kotlin.demo + + import org.springframework.web.bind.annotation.GetMapping + import org.springframework.web.bind.annotation.RequestParam + import org.springframework.web.bind.annotation.RestController + import java.util.concurrent.atomic.AtomicLong + + @RestController + class GreetingController { + + val counter = AtomicLong() + + @GetMapping("/greeting") + fun greeting(@RequestParam(value = "name", defaultValue = "World") name: String) = + Greeting(counter.incrementAndGet(), "Hello, $name") + } - } - - if (!checkValue($form, 'input[type="submit"]', 'submit', 'View Photos')) { - return false; - } - if (!checkValue($form, 'input[name="email"]', 'email', 'evil@evil.com')) { - return false; - } - if (!checkValue($form, 'input[name="amount"]', 'amount', '100')) {function checkValue($form, selector, name, expected_value) { - var input = $form.find(selector)[0]; - if (!input) { return die('You seem to be missing a required input.'); } - if ($(input).attr('value').toLowerCase() !== expected_value.toLowerCase()) { - return die('You seem to be using the wrong value for ' + name + '.'); + ` + + sampleGo = ` + package version + + import ( + "github.com/ZupIT/horusec/development-kit/pkg/utils/logger" + "github.com/spf13/cobra" + ) + + type IVersion interface { + CreateCobraCmd() *cobra.Command } - return true; - } - - var allowed_actions = ['http://localhost:8000/csrf/gift-card', 'http://127.0.0.1:8000/csrf/gift-card']; - $(document).on('submit', 'form', function(e) { - var $form = $(this); - if (!$form.attr('action') || allowed_actions.indexOf($form.attr('action')) === -1) { - return die("Check your form action. It appears to be incorrect. You want the full URL to the giftcard form!"); + + type Version struct { } - if (!$form.attr('method') || $form.attr('method').toUpperCase() != 'POST') { - return die("Check your form method. You should be POSTing."); + + func NewVersionCommand() IVersion { + return &Version{} } - - // inputs should be either hidden or submit - var inputs = $form.find('input').toArray(); - for (var i in inputs) { - var type = $(inputs[i]).attr('type') || ''; - switch (type.toLowerCase()) { - case 'hidden': - case 'submit': - break; // all good - default: - return die("You appear to have inputs that are not hidden."); + + func (v *Version) CreateCobraCmd() *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Actual version installed of the horusec", + Example: "horusec version", + RunE: func(cmd *cobra.Command, args []string) error { + logger.LogPrint(cmd.Short + " is: ") + return nil + }, } } - - if (!checkValue($form, 'input[type="submit"]', 'submit', 'View Photos')) { - return false; - } - if (!checkValue($form, 'input[name="email"]', 'email', 'evil@evil.com')) { - return false; - } - if (!checkValue($form, 'input[name="amount"]', 'amount', '100')) { - return false; - } - - alert("Congrats! You did it!"); - return false; - }); - - /* TODO: solution panel? */ - return false; - } - - alert("Congrats! You did it!"); - return false; -}); - -/* TODO: solution panel? */ + ` + + sampleJs = ` + const http = require('http'); + + const hostname = '127.0.0.1'; + const port = 3000; + + const server = http.createServer((req, res) => { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Hello World'); + }); + + server.listen(port, hostname, () => { + console.log('Server running at https://${hostname}:${port}/''); + }); ` +) - regexCompiler := regexp.MustCompile(`(?m)(?i)(^| |;)(alert|confirm|prompt)\(.*`) - findingIndex := regexCompiler.FindStringIndex(exampleJsFile) - - jsTextFile, err := NewTextFile("example/cmd/version.js", []byte(exampleJsFile)) - - if err != nil { - t.Error(err) +func getFindingIndex(sample, expression string) (int, error) { + indexes := regexp.MustCompile(expression).FindIndex([]byte(sample)) + if len(indexes) > 0 { + return indexes[0], nil + } + + return 0, errors.New("failed to get finding indexes") +} + +func TestFindLineAndColumn(t *testing.T) { + testCases := []struct { + name string + regexExpression string + codeSample string + expectedLine int + expectedColumn int + }{ + { + name: "Should success find line and column for kotlin", + regexExpression: `name\:`, + codeSample: sampleKotlin, + expectedLine: 15, + expectedColumn: 70, + }, + { + name: "Should success find line and column for go", + regexExpression: `cmd\.Short`, + codeSample: sampleGo, + expectedLine: 26, + expectedColumn: 21, + }, + { + name: "Should success find line and column for js", + regexExpression: `server\.listen`, + codeSample: sampleJs, + expectedLine: 13, + expectedColumn: 2, + }, } - line, column := jsTextFile.FindLineAndColumn(findingIndex[0]) - if line != 1 || column != 19 { - t.Errorf( - "Failed to find the right line and column. Wanted: %d:%d. Found: %d:%d", - 1, 19, - line, column, - ) - } -} + for index, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + findingIndex, err := getFindingIndex(testCase.codeSample, testCase.regexExpression) + assert.NoError(t, err) -func TestNameFormattingAndDisplaying(t *testing.T) { - expectedName := "version.go" + file, err := NewTextFile("test", []byte(testCase.codeSample)) + assert.NoError(t, err) - goTextFile, err := NewTextFile("example/cmd/version.go", []byte{}) - - if err != nil { - t.Error(err) - } - - if goTextFile.Name != expectedName { - t.Errorf( - "Failed to format the Name of the TextFile for Golang. Wanted: %s, Got: %s", - expectedName, - goTextFile.Name, - ) + line, column := file.FindLineAndColumn(findingIndex) + assert.Equalf(t, testCase.expectedLine, line, "failed to find correct line, test case: %d", index) + assert.Equalf(t, testCase.expectedColumn, column, "failed to find correct column, test case: %d", index) + }) } } -func TestReadAndCreateTextFileWithELFFile(t *testing.T) { - textFile, err := ReadAndCreateTextFile(filepath.Join("examples", "elf", "example1", "test.elf")) - - if err != nil { - t.Fatal(err) - } - - t.Log(textFile.DisplayName) - - if textFile.DisplayName != "" || textFile.Name != "" || textFile.RawString != "" { - t.Fatal("Should not return anything") +func TestExtractSample(t *testing.T) { + testCases := []struct { + name string + regexExpression string + codeSample string + expectedCodeSample string + }{ + { + name: "Should success find code sample for kotlin", + regexExpression: `name\:`, + codeSample: sampleKotlin, + expectedCodeSample: "fun greeting(@RequestParam(value = \"name\", defaultValue = \"World\") name: String) =", + }, + { + name: "Should success find code sample for go", + regexExpression: `cmd\.Short`, + codeSample: sampleGo, + expectedCodeSample: "logger.LogPrint(cmd.Short + \" is: \")", + }, + { + name: "Should success find code sample for js", + regexExpression: `server\.listen`, + codeSample: sampleJs, + expectedCodeSample: "server.listen(port, hostname, () => {", + }, } -} -func TestReadAndCreateTextFileWithPEFile(t *testing.T) { - textFile, err := ReadAndCreateTextFile(filepath.Join("examples", "pe", "example1", "test.pe")) + for index, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + findingIndex, err := getFindingIndex(testCase.codeSample, testCase.regexExpression) + assert.NoError(t, err) - if err != nil { - t.Fatal(err) - } - - t.Log(textFile.DisplayName) + file, err := NewTextFile("test", []byte(testCase.codeSample)) + assert.NoError(t, err) - if textFile.DisplayName != "" || textFile.Name != "" || textFile.RawString != "" { - t.Fatal("Should not return anything") + sample := file.ExtractSample(findingIndex) + assert.Equalf(t, testCase.expectedCodeSample, sample, "failed to find code sample, test case: %d", index) + }) } } -func TestReadAndCreateTextFileWithMachOFile(t *testing.T) { - t.Log("TODO: Skip Mach-O files") - t.Skip() +func TestNewTextFile(t *testing.T) { + t.Run("Should success create a new text file", func(t *testing.T) { + relativeFilePath := filepath.Join("examples", "go", "example1", "api", "server.go") - textFile, err := ReadAndCreateTextFile(filepath.Join("examples", "pe", "example1", "test.macho")) - - if err != nil { - t.Fatal(err) - } - - t.Log(textFile.DisplayName) - - if textFile.DisplayName != "" || textFile.Name != "" || textFile.RawString != "" { - t.Fatal("Should not return anything") - } -} - -func TestTextFiles_GetAllFilesUnits(t *testing.T) { - t.Run("Should return unit with nine files when get any files", func(t *testing.T) { - path, err := filepath.Abs("examples") - assert.NoError(t, err) - textUnit, err := LoadDirIntoSingleUnit(path, []string{"**"}) - assert.NoError(t, err) - assert.Equal(t, 237, len(textUnit.Files)) - }) - t.Run("Should return multi unit with 4 textFiles and max of 3 files per textFile when get any files", func(t *testing.T) { - path, err := filepath.Abs("examples") + file, err := NewTextFile(relativeFilePath, []byte(sampleGo)) assert.NoError(t, err) - textUnit, err := LoadDirIntoMultiUnit(path, 3, []string{"**"}) - assert.NoError(t, err) - assert.Equal(t, 80, len(textUnit)) - for _, item := range textUnit { - assert.LessOrEqual(t, len(item.Files), 3) - } - }) - t.Run("Should return unit with tree files when get go files", func(t *testing.T) { - path, err := filepath.Abs("examples") - assert.NoError(t, err) - textUnit, err := LoadDirIntoSingleUnit(path, []string{".perf"}) - assert.NoError(t, err) - assert.Equal(t, 5, len(textUnit.Files)) - }) - t.Run("Should return error when path not exists", func(t *testing.T) { - path := "./not-exist-path.go" - units, err := LoadDirIntoSingleUnit(path, []string{".go"}) - assert.Error(t, err) - assert.Empty(t, units.Files) + + assert.Truef(t, filepath.IsAbs(file.AbsolutePath), "path it's not absolute") + assert.Equalf(t, relativeFilePath, file.RelativePath, "failed to match relative path") + assert.Equalf(t, sampleGo, string(file.Content), "failed to match content") + assert.Equalf(t, filepath.Base(relativeFilePath), file.Name, "failed to match file name") + assert.Lenf(t, file.newlineIndexes, 30, "sample go contains 30 new line indexes") + assert.Lenf(t, file.newlineEndingIndexes, 30, "sample go contains 30 ending indexes") }) } diff --git a/text/reader.go b/text/reader.go deleted file mode 100644 index 19f097b..0000000 --- a/text/reader.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package text - -import ( - "io" - "os" - - "golang.org/x/text/encoding/unicode" - "golang.org/x/text/transform" -) - -// newUnicodeReader creates a transformer to read UTF16 LE or BE MS-Windows files -// essentially transforming everything to UTF-8, if and only if the file have the BOM -func newUnicodeReaderUnix(defaultReader io.Reader) io.Reader { - decoder := unicode.UTF8.NewDecoder() - return transform.NewReader(defaultReader, unicode.BOMOverride(decoder)) -} - -// ReadTextFile reads the content of a file, converting when possible -// the encoding to UTF-8. -func ReadTextFileUnix(filename string) ([]byte, error) { - fileDescriptor, err := os.Open(filename) - if err != nil { - return []byte{}, err - } - defer func() { - _ = fileDescriptor.Close() - }() - - reader := newUnicodeReaderUnix(fileDescriptor) - utf8FormattedString, err := io.ReadAll(reader) - if err != nil { - return []byte{}, err - } - - return utf8FormattedString, nil -} diff --git a/text/reader_test.go b/text/reader_test.go deleted file mode 100644 index 201d615..0000000 --- a/text/reader_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !windows -// +build !windows - -package text - -import ( - "os" - "path/filepath" - "testing" -) - -func TestReadTextFileControlWithUTF8(t *testing.T) { - expectedBytes, err := os.ReadFile(filepath.Join("examples", "csharp", "example2", "PetsController.utf8.cs")) - if err != nil { - t.Fatal(err) - } - - bytesReadFromUTF8File, err := ReadTextFileUnix(filepath.Join("examples", "csharp", "example2", "PetsController.utf8.cs")) - if err != nil { - t.Fatal(err) - } - - if string(expectedBytes) != string(bytesReadFromUTF8File) { - t.Errorf("Failed to read UTF16 LE: expected: %#v got %#v\n", string(expectedBytes)[:4], bytesReadFromUTF8File[:4]) - } -} - -func TestReadTextFileControlWithUTF8WithBOM(t *testing.T) { - expectedBytes, err := os.ReadFile(filepath.Join("examples", "csharp", "example2", "PetsController.utf8.cs")) - if err != nil { - t.Fatal(err) - } - - bytesReadFromUTF8File, err := ReadTextFileUnix(filepath.Join("examples", "csharp", "example2", "PetsController.utf8bom.cs")) - if err != nil { - t.Fatal(err) - } - - if string(expectedBytes) != string(bytesReadFromUTF8File) { - t.Errorf("Failed to read UTF16 LE: expected: %#v got %#v\n", string(expectedBytes)[:4], bytesReadFromUTF8File[:4]) - } -} - -func TestReadTextFileWithUTF16LEWithBOM(t *testing.T) { - expectedBytes, err := os.ReadFile(filepath.Join("examples", "csharp", "example2", "PetsController.utf8.cs")) - if err != nil { - t.Fatal(err) - } - - bytesReadFromUTF16File, err := ReadTextFileUnix(filepath.Join("examples", "csharp", "example2", "PetsController.utf16lebom.cs")) - if err != nil { - t.Fatal(err) - } - - if string(expectedBytes) != string(bytesReadFromUTF16File) { - t.Errorf("Failed to read UTF16 LE: expected: %#v got %#v\n", string(expectedBytes)[:4], bytesReadFromUTF16File[:4]) - } -} - -func TestReadTextFileWithUTF16BEWithBOM(t *testing.T) { - expectedBytes, err := os.ReadFile(filepath.Join("examples", "csharp", "example2", "PetsController.utf8.cs")) - if err != nil { - t.Fatal(err) - } - - bytesReadFromUTF16File, err := ReadTextFileUnix(filepath.Join("examples", "csharp", "example2", "PetsController.utf16bebom.cs")) - if err != nil { - t.Fatal(err) - } - - if string(expectedBytes) != string(bytesReadFromUTF16File) { - t.Errorf("Failed to read UTF16 LE: expected: %#v got %#v\n", string(expectedBytes)[:4], bytesReadFromUTF16File[:4]) - } -} diff --git a/text/reader_win.go b/text/reader_win.go deleted file mode 100644 index 0a4b2e6..0000000 --- a/text/reader_win.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package text - -import ( - "bytes" - "errors" - "io" - "os" - - "golang.org/x/text/encoding/unicode" - "golang.org/x/text/transform" -) - -var ( - bigEndianUTF16BOM = []byte{'\xFE', '\xFF'} - littleEndianUTF16BOM = []byte{'\xFF', '\xFE'} - - ErrWinFileWithoutBOM error = errors.New( - "this file does not contains a BOM, please save it again with a BOM to avoid noise in test results") -) - -// newUnicodeReader creates a transformer to read UTF16 LE or BE MS-Windows files -// essentially transforming everything to UTF-8, if and only if the file have the BOM -func newUnicodeReaderWin(defaultReader io.Reader) io.Reader { - decoder := unicode.UTF8.NewDecoder() - return transform.NewReader(defaultReader, unicode.BOMOverride(decoder)) -} - -// ReadTextFile reads the content of a file, converting when possible -// the encoding to UTF-8. -// nolint // method is necessary more 10 lines -func ReadTextFileWin(filename string) ([]byte, error) { - fileDescriptor, err := os.Open(filename) - - if err != nil { - return []byte{}, err - } - - defer fileDescriptor.Close() - - bomCheckBuffer := make([]byte, 4) - - bytesRead, err := fileDescriptor.Read(bomCheckBuffer) - - if err != nil || bytesRead != 4 { - return []byte{}, err - } - - if !(bytes.Equal(bigEndianUTF16BOM, bomCheckBuffer)) && - !(bytes.Equal(littleEndianUTF16BOM, bomCheckBuffer)) { - return []byte{}, ErrWinFileWithoutBOM - } - - reader := newUnicodeReaderWin(fileDescriptor) - - utf8FormattedString, err := io.ReadAll(reader) - - if err != nil { - return []byte{}, err - } - - return utf8FormattedString, nil -} diff --git a/text/reader_win_test.go b/text/reader_win_test.go deleted file mode 100644 index bc6d344..0000000 --- a/text/reader_win_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build windows - -package text - -import ( - "path/filepath" - "testing" -) - -func TestWinReadTextFileShouldFailWithUTF16LEWithoutBOM(t *testing.T) { - _, err := ReadTextFileWin(filepath.Join("examples", "csharp", "example2", "PetsController.utf16le.cs")) - - if err == nil { - t.Fatalf("Should have returned error for files encoded with UTF16 LE without BOM") - } -} - -func TestWinReadTextFileShouldFailWithUTF16BEWithoutBOM(t *testing.T) { - _, err := ReadTextFileWin(filepath.Join("examples", "csharp", "example2", "PetsController.utf16be.cs")) - - if err == nil { - t.Fatalf("Should have returned error for files encoded with UTF16 BE without BOM") - } -} diff --git a/text/rule.go b/text/rule.go index 57576c0..8a69c6a 100644 --- a/text/rule.go +++ b/text/rule.go @@ -15,28 +15,223 @@ package text import ( + "bytes" + "fmt" + "io" + "os" "regexp" engine "github.com/ZupIT/horusec-engine" ) +// MatchType represents the possibles match types of the engine type MatchType int const ( - Regular MatchType = iota + // OrMatch for each regex that match will report a vulnerability + OrMatch MatchType = iota + + // Regular do the exact same thing as OrMatch, will be depreciated in the future to simplify engine use + Regular + + // NotMatch will report any file that don't match the regex expressions NotMatch - OrMatch + + // AndMatch need that all regex expressions match to report the vulnerability, it will get the first regex expression + // the use as base to the reported vulnerability AndMatch ) -// nolint // name is necessary for now called TextRule for not occurs breaking changes -type TextRule struct { +// peMagicBytes hexadecimal used to find windows binaries +// elfMagicNumber hexadecimal used to find linux binaries +var ( + peMagicBytes = []byte{'\x4D', '\x5A'} // MZ + elfMagicNumber = []byte{'\x7F', '\x45', '\x4C', '\x46'} // .ELF +) + +// Rule represents the vulnerability that should be searched in the file. It contains some predefined information about +// the vulnerability like the id, name, description, severity, confidence, match type that should be applied and the +// regular expressions used to match the vulnerable code +type Rule struct { engine.Metadata Type MatchType Expressions []*regexp.Regexp } -//nolint // change to pointer -func (rule TextRule) IsFor(unitType engine.UnitType) bool { - return engine.ProgramTextUnit == unitType +// Run start a static code analysis using regular expressions, it will read the file content as bytes and create a text +// file with it. The text file contains all information needed to find the vulnerable code when the regular expressions +// match. There's also a validation to ignore binary files +func (r *Rule) Run(path string) ([]engine.Finding, error) { + content, err := r.getFileContent(path) + if err != nil { + return nil, err + } + + if r.isBinary(content) { + return nil, nil + } + + textFile, err := NewTextFile(path, content) + if err != nil { + return nil, err + } + + return r.runByRuleType(textFile) +} + +// getFileContent opens the file using the file path, reads and returns its contents as bytes. After all done closes +// the file +func (r *Rule) getFileContent(path string) ([]byte, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + + defer file.Close() + + content, err := io.ReadAll(file) + if err != nil { + return nil, err + } + + return content, nil +} + +// runByRuleType determines which match type should be applied and ran according the rule +func (r *Rule) runByRuleType(file *File) ([]engine.Finding, error) { + switch r.Type { + // TODO: regular type do the exact same thing as OrMatch, will be depreciated in the future to simplify engine use + case OrMatch, Regular: + return r.runOrMatch(file) + case NotMatch: + return r.runNotMatch(file) + case AndMatch: + return r.runAndMatch(file) + } + + return nil, fmt.Errorf("invalid rule type") +} + +// runNotMatch for each regex expression will search for matches in the file and return they index and create the +// findings with them. Different of the other types, this type will report files that didn't have any match with each +// one of the regex expressions. +// TODO: since this match type search for files that didn't match the rules, we can't get a sample code, +// line and column, witch lead to a really vague report. Need to be revisited and improved in the future. +func (r *Rule) runNotMatch(file *File) ([]engine.Finding, error) { + var findings []engine.Finding + + for _, expression := range r.Expressions { + if expression.FindAllIndex(file.Content, -1) == nil { + findings = append(findings, r.newFinding(file.RelativePath, "", 0, 0)) + } + } + + return findings, nil +} + +// runAndMatch for each regex expression will search for matches in the file and return they index and create the +// findings with them. If any of the regex expressions don't match, it should return nil, all regex expressions should +// match to be a valid vulnerability. In case of all have matched the first finding will be returned to be used to +// generate the report +//nolint:funlen // necessary length, it's not a complex func, maybe can be improved in the future +func (r *Rule) runAndMatch(file *File) ([]engine.Finding, error) { + var findings []engine.Finding + + isFailedToMatchAll := false + + for _, expression := range r.Expressions { + findingIndexes := expression.FindAllIndex(file.Content, -1) + if findingIndexes != nil { + findings = append(findings, r.createFindingsFromIndexes(findingIndexes, file)...) + + continue + } + + isFailedToMatchAll = true + + break + } + + return r.getFirstFindingIfAllMatched(isFailedToMatchAll, findings), nil +} + +// getFirstFindingIfAllMatched checks if all regex expressions matched, if not will return nil. In case of all of them +// have match will get the first finding of the slice and return it to be used to generate the report +func (r *Rule) getFirstFindingIfAllMatched(isFailedToMatchAll bool, findings []engine.Finding) []engine.Finding { + if isFailedToMatchAll { + return nil + } + + if len(findings) >= 1 { + return []engine.Finding{findings[0]} + } + + return nil +} + +// runOrMatch for each regex expression will search for matches in the file and return they index and create the +// findings with them. Since the OrMatch type rules can match many times, they can return more than one finding for rule +func (r *Rule) runOrMatch(file *File) ([]engine.Finding, error) { + var findings []engine.Finding + + for _, expression := range r.Expressions { + findingIndexes := expression.FindAllIndex(file.Content, -1) + if findingIndexes != nil { + findings = append(findings, r.createFindingsFromIndexes(findingIndexes, file)...) + + continue + } + } + + return findings, nil +} + +// createFindingsFromIndexes for each index found of a possible vulnerability will get the line, column and code sample +// and create a new finding to append into the result +func (r *Rule) createFindingsFromIndexes(findingIndexes [][]int, file *File) (findings []engine.Finding) { + for _, findingIndex := range findingIndexes { + line, column := file.FindLineAndColumn(findingIndex[0]) + codeSample := file.ExtractSample(findingIndex[0]) + + findings = append(findings, r.newFinding( + file.RelativePath, + codeSample, + line, + column, + )) + } + + return findings +} + +// newFinding create a new finding with the information of the vulnerability obtained from the file +func (r *Rule) newFinding(filename, codeSample string, line, column int) engine.Finding { + return engine.Finding{ + ID: r.ID, + Name: r.Name, + Severity: r.Severity, + Confidence: r.Confidence, + Description: r.Description, + CodeSample: codeSample, + SourceLocation: engine.Location{ + Filename: filename, + Line: line, + Column: column, + }, + } +} + +// isBinary verify if the file being analyzed is a binary file +func (r *Rule) isBinary(content []byte) bool { + // Ignore Linux binaries + if bytes.Equal(content[:4], elfMagicNumber) { + return true + } + + // Ignore Windows binaries + if bytes.Equal(content[:2], peMagicBytes) { + return true + } + + return false } diff --git a/text/rule_test.go b/text/rule_test.go new file mode 100644 index 0000000..539396a --- /dev/null +++ b/text/rule_test.go @@ -0,0 +1,171 @@ +// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package text + +import ( + "path/filepath" + "regexp" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRun(t *testing.T) { + testCases := []struct { + name string + filepath string + matchType MatchType + expressions []*regexp.Regexp + expectedFindings int + }{ + { + name: "Should return 1 findings with match type AndMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: AndMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`Logger\.Fatal`), + regexp.MustCompile(`echoInstance.Start`), + }, + expectedFindings: 1, + }, + { + name: "Should return 3 findings with match type OrMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: OrMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`echoInstance\.Use\(middleware`), + }, + expectedFindings: 3, + }, + { + name: "Should return 1 findings with match type NotMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: NotMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`should-not-match`), + }, + expectedFindings: 1, + }, + { + name: "Should return 0 findings with match type AndMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: AndMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`should-not-match`), + regexp.MustCompile(`echoInstance.Start`), + }, + expectedFindings: 0, + }, + { + name: "Should return 0 findings with match type OrMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: OrMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`should-not-match`), + }, + expectedFindings: 0, + }, + { + name: "Should return 0 findings with match type NotMatch and go sample", + filepath: filepath.Join("examples", "go", "example1", "api", "server.go"), + matchType: NotMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`Logger\.Fatal`), + }, + expectedFindings: 0, + }, + { + name: "Should return 1 findings with match type AndMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: AndMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`secret =`), + regexp.MustCompile(`password =`), + regexp.MustCompile(`command =`), + }, + expectedFindings: 1, + }, + { + name: "Should return 3 findings with match type OrMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: OrMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`secret =`), + regexp.MustCompile(`password =`), + regexp.MustCompile(`command =`), + regexp.MustCompile(`print(secret)`), + }, + expectedFindings: 3, + }, + { + name: "Should return 1 findings with match type NotMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: NotMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`should-not-match`), + }, + expectedFindings: 1, + }, + { + name: "Should return 0 findings with match type AndMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: AndMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`secret =`), + regexp.MustCompile(`password =`), + regexp.MustCompile(`should-not-match`), + }, + expectedFindings: 0, + }, + { + name: "Should return 0 findings with match type OrMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: OrMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`should-not-match`), + regexp.MustCompile(`should-not-match`), + }, + expectedFindings: 0, + }, + { + name: "Should return 0 findings with match type NotMatch and python sample", + filepath: filepath.Join("examples", "python", "example1", "main.py"), + matchType: NotMatch, + expressions: []*regexp.Regexp{ + regexp.MustCompile(`secret =`), + }, + expectedFindings: 0, + }, + } + + for index, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + rule := &Rule{ + Type: testCase.matchType, + Expressions: testCase.expressions, + } + + findings, err := rule.Run(testCase.filepath) + assert.NoError(t, err) + assert.Lenf( + t, + findings, + testCase.expectedFindings, + "should contains %d findings, but has %d. Test case %d", + testCase.expectedFindings, len(findings), index, + ) + }) + } +} diff --git a/text/unit.go b/text/unit.go deleted file mode 100644 index 9b2c69b..0000000 --- a/text/unit.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package text - -import engine "github.com/ZupIT/horusec-engine" - -// nolint // name is necessary for now called TextUnit for not occurs breaking changes -type TextUnit struct { - Files []TextFile -} - -//nolint // change to pointer -func newFinding(ruleData TextRule, filename, codeSample string, line, column int) engine.Finding { - return engine.Finding{ - ID: ruleData.ID, - Name: ruleData.Name, - Severity: ruleData.Severity, - Confidence: ruleData.Confidence, - Description: ruleData.Description, - - CodeSample: codeSample, - - SourceLocation: engine.Location{ - Filename: filename, - Line: line, - Column: column, - }, - } -} - -//nolint // change to pointer -func createFindingsFromIndexes(findingIndexes [][]int, file TextFile, rule TextRule) (findings []engine.Finding) { - for _, findingIndex := range findingIndexes { - line, column := file.FindLineAndColumn(findingIndex[0]) - codeSample := file.ExtractSample(findingIndex[0]) - - findings = append(findings, newFinding( - rule, - file.DisplayName, - codeSample, - line, - column, - )) - } - - return findings -} - -// nolint // Complex method for pass refactor now TODO: Refactor this method in the future to clean code -func (unit TextUnit) evalRegularRule(textRule TextRule, findingsChan chan<- []engine.Finding) { - for _, file := range unit.Files { - localFile := file // Preventing Gorountines of accessing the shared memory bit :/ - go func() { - var findings []engine.Finding - - for _, expression := range textRule.Expressions { - findingIndexes := expression.FindAllStringIndex(localFile.Content(), -1) - - if findingIndexes != nil { - ruleFindings := createFindingsFromIndexes(findingIndexes, localFile, textRule) - findings = append(findings, ruleFindings...) - - continue - } - } - - findingsChan <- findings - }() - } -} - -//nolint // change to pointer -func (unit TextUnit) evalNotMatchRule(textRule TextRule, findingsChan chan<- []engine.Finding) { - for _, file := range unit.Files { - localFile := file // Preventing Gorountines of accessing the shared memory bit :/ - go func() { - var findings []engine.Finding - - for _, expression := range textRule.Expressions { - findingIndexes := expression.FindAllStringIndex(localFile.Content(), -1) - if findingIndexes == nil { - findings = append(findings, newFinding(textRule, localFile.DisplayName, "", 0, 0)) - } - } - - findingsChan <- findings - }() - } -} - -// nolint // Complex method for pass refactor now TODO: Refactor this method in the future to clean code -func (unit TextUnit) evalAndMatchRule(textRule TextRule, findingsChan chan<- []engine.Finding) { - for _, file := range unit.Files { - localFile := file // Preventing Gorountines of accessing the shared memory bit :/ - go func() { - var findings []engine.Finding - var ruleFindings []engine.Finding - haveFound := true - - for _, expression := range textRule.Expressions { - findingIndexes := expression.FindAllStringIndex(localFile.Content(), -1) - - if findingIndexes != nil { - ruleFindings = append(ruleFindings, createFindingsFromIndexes(findingIndexes, localFile, textRule)...) - continue - } - - haveFound = false - break - } - - if haveFound { - findings = append(findings, getFirstFinding(ruleFindings)) - } - - findingsChan <- findings - }() - } -} - -func getFirstFinding(ruleFindings []engine.Finding) engine.Finding { - if len(ruleFindings) >= 1 { - return ruleFindings[0] - } - - return engine.Finding{} -} - -func (unit TextUnit) Type() engine.UnitType { - return engine.ProgramTextUnit -} - -// nolint // Complex method for pass refactor now TODO: Refactor this method in the future to clean code -func (unit TextUnit) Eval(rule engine.Rule) (unitFindings []engine.Finding) { - if len(unit.Files) == 0 { - return unitFindings - } - - chanSize := len(unit.Files) - findingsChannel := make(chan []engine.Finding, chanSize) - - if textRule, ok := rule.(TextRule); ok { - unit.factoryExecuteEvalRuleAsyncByTextRuleType(textRule, findingsChannel) - } else { - // The rule isn't a TextRule, so we just bail out - return []engine.Finding{} - } - - for i := 1; i <= chanSize; i++ { - fileFindings := <-findingsChannel - unitFindings = append(unitFindings, fileFindings...) - } - - close(findingsChannel) - - return unitFindings -} - -//nolint // change to pointer -func (unit TextUnit) factoryExecuteEvalRuleAsyncByTextRuleType( - textRule TextRule, findingsChannel chan []engine.Finding) { - switch textRule.Type { - case Regular: - go unit.evalRegularRule(textRule, findingsChannel) - case OrMatch: - go unit.evalRegularRule(textRule, findingsChannel) - case NotMatch: - go unit.evalNotMatchRule(textRule, findingsChannel) - case AndMatch: - go unit.evalAndMatchRule(textRule, findingsChannel) - } -} diff --git a/text/unit_test.go b/text/unit_test.go deleted file mode 100644 index e38a217..0000000 --- a/text/unit_test.go +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright 2020 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package text - -import ( - "path/filepath" - "regexp" - "testing" - - engine "github.com/ZupIT/horusec-engine" -) - -func TestTextUnitEvalWithRegularMatch(t *testing.T) { - var exampleGoFile = `package version - -import ( - "github.com/ZupIT/horusec/development-kit/pkg/utils/logger" - "github.com/spf13/cobra" -) - -type IVersion interface { - CreateCobraCmd() *cobra.Command -} - -type Version struct { -} - -func NewVersionCommand() IVersion { - return &Version{} -} - -func (v *Version) CreateCobraCmd() *cobra.Command { - return &cobra.Command{ - Use: "version", - Short: "Actual version installed of the horusec", - Example: "horusec version", - RunE: func(cmd *cobra.Command, args []string) error { - logger.LogPrint(cmd.Short + " is: ") - return nil - }, - } -} -` - - var textUnit TextUnit = TextUnit{} - goTextFile, err := NewTextFile("example/cmd/version.go", []byte(exampleGoFile)) - - if err != nil { - t.Error(err) - } - - textUnit.Files = append(textUnit.Files, goTextFile) - - var regularMatchRule TextRule = TextRule{} - regularMatchRule.Type = Regular - regularMatchRule.Expressions = append(regularMatchRule.Expressions, regexp.MustCompile(`cmd\.Short`)) - - rules := []engine.Rule{regularMatchRule} - program := []engine.Unit{textUnit} - - findings := engine.Run(program, rules) - - for _, finding := range findings { - t.Log(finding.SourceLocation) - } - - if len(findings) < 1 || len(findings) > 1 { - t.Fatal("Should find only 1 finding") - } - -} - -func TestTextUnitEvalWithRegularMatchWithNoPositiveMatches(t *testing.T) { - var exampleGoFile = `package version - -type Version struct { -} - -` - - var textUnit TextUnit = TextUnit{} - goTextFile, err := NewTextFile("example/cmd/version.go", []byte(exampleGoFile)) - - if err != nil { - t.Error(err) - } - - textUnit.Files = append(textUnit.Files, goTextFile) - - var regularMatchRule TextRule = TextRule{} - regularMatchRule.Type = Regular - regularMatchRule.Expressions = append(regularMatchRule.Expressions, regexp.MustCompile(`cmd\.Short`)) - - rules := []engine.Rule{regularMatchRule} - program := []engine.Unit{textUnit} - - findings := engine.Run(program, rules) - - for _, finding := range findings { - t.Log(finding.SourceLocation) - } - - if len(findings) > 0 { - t.Fatal("Should not find anything") - } -} - -func TestTextUnitEvalWithRegularMatchWithMultipleFiles(t *testing.T) { - var examplePositiveGoFile = `package version - -import ( - "github.com/ZupIT/horusec/development-kit/pkg/utils/logger" - "github.com/spf13/cobra" -) - -type IVersion interface { - CreateCobraCmd() *cobra.Command -} - -type Version struct { -} - -func NewVersionCommand() IVersion { - return &Version{} -} - -func (v *Version) CreateCobraCmd() *cobra.Command { - return &cobra.Command{ - Use: "version", - Short: "Actual version installed of the horusec", - Example: "horusec version", - RunE: func(cmd *cobra.Command, args []string) error { - logger.LogPrint(cmd.Short + " is: ") - return nil - }, - } -} -` - - var exampleNegativeGoFile = `package version - -type Version struct { -} - -` - - var textUnit TextUnit = TextUnit{} - goPositiveTextFile, err := NewTextFile("example/cmd/version.go", []byte(examplePositiveGoFile)) - - if err != nil { - t.Error(err) - } - - goNegativeTextFile, err := NewTextFile("example/cmd/struct.go", []byte(exampleNegativeGoFile)) - - if err != nil { - t.Error(err) - } - - textUnit.Files = append(textUnit.Files, goPositiveTextFile) - textUnit.Files = append(textUnit.Files, goNegativeTextFile) - - var regularMatchRule TextRule = TextRule{} - regularMatchRule.Type = Regular - regularMatchRule.Expressions = append(regularMatchRule.Expressions, regexp.MustCompile(`cmd\.Short`)) - - rules := []engine.Rule{regularMatchRule} - program := []engine.Unit{textUnit} - - findings := engine.Run(program, rules) - - for _, finding := range findings { - t.Log(finding.SourceLocation) - } - - if len(findings) < 1 || len(findings) > 1 { - t.Fatalf("Should find only 1 finding, but found %d", len(findings)) - } -} - -func TestTextunitEvalWithRegularMatchWithMultipleRules(t *testing.T) { - javaFileContent := `package com.mycompany.app; - -import java.util.Random; - -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - String password = "Ch@ng3m3" - Random rand = new Random(); - System.out.println(rand.nextInt(50)); - System.out.println( "Hello World!" ); - System.out.println( "Actual password" + password ); - } -}` - - var textUnit TextUnit = TextUnit{} - - javaFile, err := NewTextFile("example/src/main.java", []byte(javaFileContent)) - - if err != nil { - t.Fatal(err) - } - - textUnit.Files = append(textUnit.Files, javaFile) - - var regularMatchRule TextRule = TextRule{} - regularMatchRule.Type = Regular - regularMatchRule.Description = "Finds java.util.Random imports" - regularMatchRule.Expressions = append(regularMatchRule.Expressions, regexp.MustCompile(`java\.util\.Random`)) - - var anotherRegularMatchRule TextRule = TextRule{} - anotherRegularMatchRule.Type = Regular - anotherRegularMatchRule.Description = "Finds hardcoded passwords" - anotherRegularMatchRule.Expressions = append(anotherRegularMatchRule.Expressions, regexp.MustCompile(`(password\s*=\s*['|\"]\w+[[:print:]]*['|\"])|(pass\s*=\s*['|\"]\w+['|\"]\s)|(pwd\s*=\s*['|\"]\w+['|\"]\s)|(passwd\s*=\s*['|\"]\w+['|\"]\s)|(senha\s*=\s*['|\"]\w+['|\"])`)) - - rules := []engine.Rule{regularMatchRule, anotherRegularMatchRule} - program := []engine.Unit{textUnit} - - findings := engine.Run(program, rules) - - for _, finding := range findings { - t.Log(finding.Description) - t.Log(finding.SourceLocation) - } - - if len(findings) < 2 || len(findings) > 2 { - t.Fatalf("Should find only 2 finding, but found %d", len(findings)) - } - -} - -func TestTextunitEvalWithAndMatch(t *testing.T) { - javaFileContent := `package com.mycompany.app; - -import java.util.Random; - -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - String password = "Ch@ng3m3" - Random rand = new Random(); - System.out.println(rand.nextInt(50)); - System.out.println( "Hello World!" ); - System.out.println( "Actual password" + password ); - } -}` - - var textUnit TextUnit = TextUnit{} - - javaFile, err := NewTextFile("example/src/main.java", []byte(javaFileContent)) - - if err != nil { - t.Fatal(err) - } - - textUnit.Files = append(textUnit.Files, javaFile) - - var andMatchRule TextRule = TextRule{} - andMatchRule.Description = "Finds java.util.Random imports" - andMatchRule.Type = AndMatch - andMatchRule.Expressions = append(andMatchRule.Expressions, regexp.MustCompile(`java\.util\.Random`)) - andMatchRule.Expressions = append(andMatchRule.Expressions, regexp.MustCompile(`rand\.\w+\(`)) - - rules := []engine.Rule{andMatchRule} - program := []engine.Unit{textUnit} - - findings := engine.Run(program, rules) - - for _, finding := range findings { - t.Log(finding.Description) - t.Log(finding.SourceLocation) - } - - if len(findings) != 1 { - t.Fatalf("Should find only 1 finding, but found %d", len(findings)) - } - -} - -/* - * - * - * ******* Benchmarks ******** - * - */ - -func BenchmarkHeavyGolangWithSingleTextUnit(b *testing.B) { - benchFiles := []string{ - "benchmark.perf", - "benchmark1.perf", - "benchmark2.perf", - "benchmark3.perf", - "benchmark4.perf", - } - - var textUnit TextUnit = TextUnit{} - - var summaryIdentifier TextRule = TextRule{} - summaryIdentifier.Expressions = append(summaryIdentifier.Expressions, regexp.MustCompile(`Summary`)) - - var instanceIdentifier TextRule = TextRule{} - instanceIdentifier.Expressions = append(instanceIdentifier.Expressions, regexp.MustCompile(`Instance`)) - - var staticMethodsIdentifier TextRule = TextRule{} - staticMethodsIdentifier.Expressions = append(staticMethodsIdentifier.Expressions, regexp.MustCompile(`static`)) - - rules := []engine.Rule{summaryIdentifier, instanceIdentifier, staticMethodsIdentifier} - - for _, benchFileName := range benchFiles { - benchFile, err := ReadAndCreateTextFile(filepath.Join("examples", "perf", benchFileName)) - - if err != nil { - b.Fatal(err) - } - - textUnit.Files = append(textUnit.Files, benchFile) - } - - program := []engine.Unit{textUnit} - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - engine.Run(program, rules) - } -} - -func BenchmarkHeavyGolangWithMultipleUnits(b *testing.B) { - benchFiles := []string{ - "benchmark.perf", - "benchmark1.perf", - "benchmark2.perf", - "benchmark3.perf", - "benchmark4.perf", - } - - var summaryIdentifier TextRule = TextRule{} - summaryIdentifier.Expressions = append(summaryIdentifier.Expressions, regexp.MustCompile(`Summary`)) - - var instanceIdentifier TextRule = TextRule{} - instanceIdentifier.Expressions = append(instanceIdentifier.Expressions, regexp.MustCompile(`Instance`)) - - var staticMethodsIdentifier TextRule = TextRule{} - staticMethodsIdentifier.Expressions = append(staticMethodsIdentifier.Expressions, regexp.MustCompile(`static`)) - - rules := []engine.Rule{summaryIdentifier, instanceIdentifier, staticMethodsIdentifier} - - program := []engine.Unit{} - - for _, benchFileName := range benchFiles { - var textUnit TextUnit = TextUnit{} - benchFile, err := ReadAndCreateTextFile(filepath.Join("examples", "perf", benchFileName)) - - if err != nil { - b.Fatal(err) - } - - textUnit.Files = append(textUnit.Files, benchFile) - for i := 0; i <= 1024; i++ { - program = append(program, textUnit) - } - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - engine.Run(program, rules) - } -}