From 6429ff5c166ce9ba826b71c35eb91cd1328cf791 Mon Sep 17 00:00:00 2001 From: Prashant Balachandran Date: Thu, 15 Apr 2021 19:29:57 +0530 Subject: [PATCH] changes for sarif format changing version of testify removed stretchr from go.sum correcting dependencies in go.mod changing function call to support older version of go --- analyses/stackanalyses/controller.go | 10 +- analyses/verbose/helper.go | 6 +- analyses/verbose/sarif_helper.go | 153 +++++++++++++++++++++++++++ cmd/analyse.go | 6 +- go.mod | 3 +- go.sum | 18 +++- 6 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 analyses/verbose/sarif_helper.go diff --git a/analyses/stackanalyses/controller.go b/analyses/stackanalyses/controller.go index fd5e26b..344ebe0 100644 --- a/analyses/stackanalyses/controller.go +++ b/analyses/stackanalyses/controller.go @@ -37,7 +37,7 @@ const ( ) //StackAnalyses is main controller function for analyse command. This function is responsible for all communications between cmd and custom packages. -func StackAnalyses(requestParams driver.RequestType, jsonOut bool, verboseOut bool) bool { +func StackAnalyses(requestParams driver.RequestType, jsonOut bool, verboseOut bool, sarifFmt bool) bool { log.Debug().Msgf("Executing StackAnalyses.") var hasVul bool matcher, err := GetMatcher(requestParams.RawManifestFile) @@ -51,7 +51,13 @@ func StackAnalyses(requestParams driver.RequestType, jsonOut bool, verboseOut bo verboseEligible := getResponse.RegistrationStatus == RegisteredStatus showVerboseMsg := verboseOut && !verboseEligible - if verboseOut && verboseEligible { + if verboseEligible && sarifFmt { + hasVul, err = verbose.ProcessSarif(getResponse, mc.fileStats.RawFilePath) + if err != nil { + log.Fatal().Err(err) + return false + } + } else if verboseOut && verboseEligible { hasVul = verbose.ProcessVerbose(getResponse, jsonOut) } else { hasVul = summary.ProcessSummary(getResponse, jsonOut, showVerboseMsg) diff --git a/analyses/verbose/helper.go b/analyses/verbose/helper.go index f93cd61..66f64a5 100644 --- a/analyses/verbose/helper.go +++ b/analyses/verbose/helper.go @@ -3,13 +3,11 @@ package verbose import ( "encoding/json" "fmt" - "os" - "sort" - "github.com/fabric8-analytics/cli-tools/utils" - "github.com/fatih/color" "github.com/rs/zerolog/log" + "os" + "sort" "github.com/fabric8-analytics/cli-tools/analyses/driver" ) diff --git a/analyses/verbose/sarif_helper.go b/analyses/verbose/sarif_helper.go new file mode 100644 index 0000000..64d511c --- /dev/null +++ b/analyses/verbose/sarif_helper.go @@ -0,0 +1,153 @@ +package verbose + +import ( + "errors" + "fmt" + "github.com/fabric8-analytics/cli-tools/analyses/driver" + "github.com/owenrumney/go-sarif/models" + "github.com/owenrumney/go-sarif/sarif" + "github.com/rs/zerolog/log" + "io/ioutil" + "os" + "regexp" + "strings" +) + +type RegexDependencyLocator struct { + FileContent string + Ecosystem string + EndIndices []int + DependencyNodeIndex []int +} + +func ProcessSarif(analysedResult driver.GetResponseType, manifestFilePath string) (bool, error) { + var hasVuln bool + report, err := sarif.New(sarif.Version210) + + if err != nil { + log.Fatal().Msg("Error forming SARIF respose") + return false, errors.New("unable to create SARIF file") + } + + run := report.AddRun("CRDA", "https://github.com/fabric8-analytics") + + regexDependencyLocator := RegexDependencyLocator{} + if len(analysedResult.AnalysedDeps) == 0 { + log.Fatal().Msg("Dependencies have not been analysed") + return false, errors.New("dependencies have not been analysed") + } + err = regexDependencyLocator.SetUp(manifestFilePath, analysedResult.AnalysedDeps[0].Ecosystem) + + if err != nil { + return false, errors.New("unable to setup dependency locator") + } + + manifestParts := strings.Split(manifestFilePath, string(os.PathSeparator)) + manifest := manifestParts[len(manifestParts) - 1] + for _, dep := range analysedResult.AnalysedDeps { + line, column := regexDependencyLocator.LocateDependency(dep.Name) + for _, publicVuln := range dep.PublicVulnerabilities { + addVulnToReport(run, publicVuln, manifest, line, column) + hasVuln = true + } + for _, privateVuln := range dep.PrivateVulnerabilities { + addVulnToReport(run, privateVuln, manifest, line, column) + hasVuln = true + } + } + + report.Write(os.Stdout) + return hasVuln, nil +} + +func addVulnToReport(run *models.Run, vuln driver.VulnerabilitiesType, manifestFilePath string, line int, column int) { + rule := run.AddRule(vuln.ID). + WithHelpURI(vuln.URL).WithDescription(vuln.Title) + + run.AddResult(rule.ID). + WithMessage(vuln.Title). + WithLevel(vuln.Severity). + WithLocationDetails(manifestFilePath, line, column) +} + + +func (r *RegexDependencyLocator) SetUp(manifestFilePath string, ecosystem string) error{ + content, err := ioutil.ReadFile(manifestFilePath) + if err != nil { + log.Fatal().Msg("Unable to load manifest File " + manifestFilePath) + return fmt.Errorf("unable to load manifest file %s" ,manifestFilePath) + } + + r.FileContent = string(content) + r.Ecosystem = ecosystem + newLineRegex, _ := regexp.Compile("\n") + + lines := newLineRegex.FindAllStringIndex(r.FileContent, -1) + r.EndIndices = make([]int, len(lines)) + // Finding the end index for each end of line + for i, line := range lines { + r.EndIndices[i] = line[1] + } + + dependenciesRegex, _ := regexp.Compile(getDependencyNodeRegex(r.Ecosystem)) + // Find the index for the start of the dependency node ( in case of pom.xml, + // dependencies: in case of package.json) + r.DependencyNodeIndex = dependenciesRegex.FindStringIndex(r.FileContent) + + return nil + +} + +func (r *RegexDependencyLocator) LocateDependency(dependency string) (int, int){ + // In case of maven the dependency consists groupId and artifactID + // Picking up the artifact ID as the dependency + if r.Ecosystem == "maven" { + dependencyParts := strings.Split(dependency, ":") + dependency = dependencyParts[len(dependencyParts) - 1] + } + // Adding the actual dependency in to the dependency regex + dependencyRegexStr := strings.Replace(getDependencyRegex(r.Ecosystem), "?", dependency, 1) + dependencyRegex, _ := regexp.Compile(dependencyRegexStr) + dependencyIndex := dependencyRegex.FindStringIndex(r.FileContent) + + var lineNum int + var column int + + // Check if the dependency index is within the dependency node + if r.DependencyNodeIndex[0] < dependencyIndex[0] && dependencyIndex[0] < r.DependencyNodeIndex[1] { + for i, val := range r.EndIndices { + // Getting the line num and column number of the dependency + if val <= dependencyIndex[0] && dependencyIndex[0] < r.EndIndices[i+1] { + lineNum = i + 2 + column = dependencyIndex[0] - val + 2 + break + } + } + } + return lineNum, column +} + +func getDependencyNodeRegex(ecosystem string) string{ + switch ecosystem { + case "npm": + return "\"dependencies\"[\\s]*:[\\s\n]*{[\\s\na-z\"\\d.,\\-:^]*}" + case "maven": + return "[\\s]*[\\s\\n]*[<>!\\s\\w\\/${}\"\\d.,\\-:^]*<\\/dependencies[\\s\\n]*>" + default: + return "[\\s\\S]*" + + } +} + +func getDependencyRegex(ecosystem string) string{ + switch ecosystem{ + case "npm": + return "\"?\"[\\s]*:[\\s\n]*\"[\\d\\.^\\-\\w]*\"" + case "maven": + return "?[\\s\\n]*<\\/artifactId[\\s\\n]*>" + default: + return "?[\\s]*==" + + } +} + diff --git a/cmd/analyse.go b/cmd/analyse.go index 6498a90..a70fcfb 100644 --- a/cmd/analyse.go +++ b/cmd/analyse.go @@ -15,6 +15,7 @@ import ( var jsonOut bool var verboseOut bool +var sarifOut bool // analyseCmd represents the analyse command var analyseCmd = &cobra.Command{ @@ -31,6 +32,7 @@ func init() { rootCmd.AddCommand(analyseCmd) analyseCmd.Flags().BoolVarP(&jsonOut, "json", "j", false, "Set output format to JSON.") analyseCmd.Flags().BoolVarP(&verboseOut, "verbose", "v", false, "Detailed Analyses Report.") + analyseCmd.Flags().BoolVarP(&sarifOut, "sarif", "s", false, "Report in Sarif format.") } // destructor deletes intermediary files used to have stack analyses @@ -76,7 +78,9 @@ func runAnalyse(cmd *cobra.Command, args []string) { if !jsonOut { fmt.Fprintln(os.Stdout, "Analysing your Dependency Stack! Please wait...") } - hasVul := sa.StackAnalyses(requestParams, jsonOut, verboseOut) + + hasVul := sa.StackAnalyses(requestParams, jsonOut, verboseOut, sarifOut) + if hasVul { // Stack has vulnerability, exit with 2 code os.Exit(2) diff --git a/go.mod b/go.mod index 6f78995..6ae1cdc 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,9 @@ require ( github.com/jpillora/backoff v1.0.0 github.com/manifoldco/promptui v0.8.0 github.com/mitchellh/go-homedir v1.1.0 + github.com/owenrumney/go-sarif v0.0.8 github.com/rs/zerolog v1.20.0 github.com/spf13/cobra v1.1.1 github.com/spf13/viper v1.7.1 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 ) diff --git a/go.sum b/go.sum index 6578476..4fa01e3 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,7 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -24,9 +25,11 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce 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/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -73,6 +76,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 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= @@ -106,6 +110,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E 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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= @@ -114,8 +119,10 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= @@ -146,6 +153,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ 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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/owenrumney/go-sarif v0.0.8 h1:rxNjz+/hm8s4+NUtq1mnvY5NbAr6RqppTzlT+QH2c28= +github.com/owenrumney/go-sarif v0.0.8/go.mod h1:fcYnVdYRfXWB943S0WaZrjAMuoTEj7vqS7JpOMf6CG0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -173,7 +182,9 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -196,8 +207,8 @@ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -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 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -295,6 +306,7 @@ 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-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -319,6 +331,7 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= @@ -329,6 +342,7 @@ gopkg.in/yaml.v2 v2.2.1/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.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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=