diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c2eede0..eeb359a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [v1.6.2] +- Updated capabilityChecker to include metrics and configure whether or not to return errors [#449](https://github.com/xmidt-org/webpa-common/pull/449) + ## [v1.6.1] - Fixed panic from assignment to entry in nil map [#453](https://github.com/xmidt-org/webpa-common/pull/453) @@ -58,7 +61,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The first official release. We will be better about documenting changes moving forward. -[Unreleased]: https://github.com/xmidt-org/webpa-common/compare/v1.6.0...HEAD +[Unreleased]: https://github.com/xmidt-org/webpa-common/compare/v1.6.2...HEAD +[v1.6.2]: https://github.com/xmidt-org/webpa-common/compare/v1.6.1...v1.6.2 +[v1.6.1]: https://github.com/xmidt-org/webpa-common/compare/v1.6.0...v1.6.1 [v1.6.0]: https://github.com/xmidt-org/webpa-common/compare/v1.5.1...v1.6.0 [v1.5.1]: https://github.com/xmidt-org/webpa-common/compare/v1.5.0...v1.5.1 [v1.5.0]: https://github.com/xmidt-org/webpa-common/compare/v1.4.0...v1.5.0 diff --git a/basculechecks/basculechecks.go b/basculechecks/basculechecks.go index 3fd97bc7..52eeed2b 100644 --- a/basculechecks/basculechecks.go +++ b/basculechecks/basculechecks.go @@ -3,9 +3,11 @@ package basculechecks import ( "context" "errors" + "fmt" "regexp" "strings" + "github.com/go-kit/kit/log" "github.com/goph/emperror" "github.com/xmidt-org/bascule" ) @@ -15,48 +17,179 @@ var ( ErrNoAuth = errors.New("couldn't get request info: authorization not found") ErrNonstringVal = errors.New("expected value to be a string") ErrNoValidCapabilityFound = errors.New("no valid capability for endpoint") + ErrNilAttributes = fmt.Errorf("nil attributes interface") ) -func CreateValidCapabilityCheck(prefix string, acceptAllMethod string) (func(context.Context, []interface{}) error, error) { - matchPrefix, err := regexp.Compile("^" + prefix + "(.+):(.+?)$") - if err != nil { - return nil, emperror.WrapWith(err, "failed to compile prefix given", "prefix", prefix) - } - return func(ctx context.Context, vals []interface{}) error { - if len(vals) == 0 { - return ErrNoVals +const ( + CapabilityKey = "capabilities" + PartnerKey = "allowedResources.allowedPartners" + DefaultRegex = `(mac|uuid|dns|serial):([^/]+)` +) + +type capabilityCheck struct { + prefixToMatch *regexp.Regexp + endpointToMatch *regexp.Regexp + acceptAllMethod string + measures *AuthCapabilityCheckMeasures +} + +var defaultLogger = log.NewNopLogger() + +func (c *capabilityCheck) CreateBasculeCheck(errorOut bool) bascule.ValidatorFunc { + return func(ctx context.Context, _ bascule.Token) error { + // if we're not supposed to error out, the outcome should be accepted on failure + failureOutcome := AcceptedOutcome + if errorOut { + // if we actually error out, the outcome is the request being rejected + failureOutcome = RejectedOutcome } auth, ok := bascule.FromContext(ctx) if !ok { - return ErrNoAuth + c.measures.CapabilityCheckOutcome.With(OutcomeLabel, failureOutcome, ReasonLabel, TokenMissing, ClientIDLabel, "", PartnerIDLabel, "", EndpointLabel, "").Add(1) + if errorOut { + return ErrNoAuth + } + return nil } - reqVal := auth.Request - for _, val := range vals { - str, ok := val.(string) - if !ok { - return ErrNonstringVal - } - matches := matchPrefix.FindStringSubmatch(str) - if matches == nil || len(matches) < 3 { - continue + client, partnerID, endpoint, reason, err := c.prepMetrics(auth) + labels := []string{ClientIDLabel, client, PartnerIDLabel, partnerID, EndpointLabel, endpoint} + if err != nil { + labels = append(labels, OutcomeLabel, failureOutcome, ReasonLabel, reason) + c.measures.CapabilityCheckOutcome.With(labels...).Add(1) + if errorOut { + return err } + return nil + } - method := matches[2] - if method != acceptAllMethod && method != strings.ToLower(reqVal.Method) { - continue + vals, reason, err := getCapabilities(auth.Token.Attributes()) + if err != nil { + labels = append(labels, OutcomeLabel, failureOutcome, ReasonLabel, reason) + c.measures.CapabilityCheckOutcome.With(labels...).Add(1) + if errorOut { + return err } + return nil + } - re := regexp.MustCompile(matches[1]) - matchIdxs := re.FindStringIndex(reqVal.URL.EscapedPath()) - if matchIdxs == nil { - continue - } - if matchIdxs[0] == 0 { - return nil + err = c.checkCapabilities(vals, auth.Request) + if err != nil { + labels = append(labels, OutcomeLabel, failureOutcome, ReasonLabel, NoCapabilitiesMatch) + c.measures.CapabilityCheckOutcome.With(labels...).Add(1) + if errorOut { + return err } + return nil + } + + labels = append(labels, OutcomeLabel, AcceptedOutcome, ReasonLabel, "") + c.measures.CapabilityCheckOutcome.With(labels...).Add(1) + return nil + } +} + +func NewCapabilityChecker(m *AuthCapabilityCheckMeasures, prefix string, acceptAllMethod string) (*capabilityCheck, error) { + if m == nil { + return nil, errors.New("nil capability check measures") + } + matchPrefix, err := regexp.Compile("^" + prefix + "(.+):(.+?)$") + if err != nil { + return nil, emperror.WrapWith(err, "failed to compile prefix given", "prefix", prefix) + } + matchEndpoint, err := regexp.Compile(DefaultRegex) + if err != nil { + return nil, emperror.WrapWith(err, "failed to compile endpoint regex given", "endpoint", DefaultRegex) + } + + c := capabilityCheck{ + prefixToMatch: matchPrefix, + endpointToMatch: matchEndpoint, + acceptAllMethod: acceptAllMethod, + measures: m, + } + return &c, nil +} + +func (c *capabilityCheck) checkCapabilities(capabilities []string, requestInfo bascule.Request) error { + urlToMatch := requestInfo.URL.EscapedPath() + methodToMatch := requestInfo.Method + for _, val := range capabilities { + matches := c.prefixToMatch.FindStringSubmatch(val) + if matches == nil || len(matches) < 3 { + continue } - return ErrNoValidCapabilityFound - }, nil + + method := matches[2] + if method != c.acceptAllMethod && method != strings.ToLower(methodToMatch) { + continue + } + + re := regexp.MustCompile(matches[1]) //url regex that capability grants access to + matchIdxs := re.FindStringIndex(requestInfo.URL.EscapedPath()) + if matchIdxs == nil { + continue + } + if matchIdxs[0] == 0 { + return nil + } + } + return emperror.With(ErrNoValidCapabilityFound, "capabilitiesFound", capabilities, "urlToMatch", urlToMatch, "methodToMatch", methodToMatch) + +} + +func (c *capabilityCheck) prepMetrics(auth bascule.Authentication) (string, string, string, string, error) { + // getting metric information + client := auth.Token.Principal() + partnerIDs, ok := auth.Token.Attributes().GetStringSlice(PartnerKey) + if !ok { + return client, "", "", UndeterminedPartnerID, fmt.Errorf("couldn't get partner IDs from attributes using key %v", PartnerKey) + } + partnerID := determinePartnerMetric(partnerIDs) + escapedURL := auth.Request.URL.EscapedPath() + i := c.endpointToMatch.FindStringIndex(escapedURL) + endpoint := escapedURL + if i != nil { + endpoint = escapedURL[:i[0]] + "..." + escapedURL[i[1]:] + } + return client, partnerID, endpoint, "", nil + +} + +func determinePartnerMetric(partners []string) string { + if len(partners) < 1 { + return "none" + } + if len(partners) == 1 { + if partners[0] == "*" { + return "wildcard" + } + return partners[0] + } + for _, partner := range partners { + if partner == "*" { + return "wildcard" + } + } + return "many" + +} + +func getCapabilities(attributes bascule.Attributes) ([]string, string, error) { + if attributes == nil { + return []string{}, UndeterminedCapabilities, ErrNilAttributes + } + + vals, ok := attributes.GetStringSlice(CapabilityKey) + if !ok { + return []string{}, UndeterminedCapabilities, fmt.Errorf("couldn't get capabilities using key %v", CapabilityKey) + } + + if len(vals) == 0 { + return []string{}, EmptyCapabilitiesList, ErrNoVals + } + + return vals, "", nil + } diff --git a/basculechecks/basculechecks_test.go b/basculechecks/basculechecks_test.go index 052e9147..86bb85fd 100644 --- a/basculechecks/basculechecks_test.go +++ b/basculechecks/basculechecks_test.go @@ -2,82 +2,498 @@ package basculechecks import ( "context" + "errors" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/xmidt-org/bascule" + "github.com/xmidt-org/webpa-common/xmetrics/xmetricstest" ) -func TestValidCapabilityCheckFail(t *testing.T) { - check, err := CreateValidCapabilityCheck(`\K`, "") - assert.NotNil(t, err) - assert.Nil(t, check) +func TestCreateBasculeCheck(t *testing.T) { + urlStr := "/good/url/for/testing" + goodURL, err := url.Parse(urlStr) + assert.Nil(t, err) + goodPrincipal := "party:ppl" + goodCapabilities := []string{ + "test:/good/for/nothing:all", + `test:/good/.*/testing\b:all`, + } + goodPartner := []string{"meh"} + + tests := []struct { + description string + errorOut bool + emptyContext bool + partnerIDs interface{} + capabilities interface{} + expectedOutcome string + expectedReason string + expectedClient string + expectedPartner string + expectedEndpoint string + expectedErr error + }{ + { + description: "Success", + partnerIDs: goodPartner, + capabilities: goodCapabilities, + expectedOutcome: AcceptedOutcome, + expectedReason: "", + expectedClient: goodPrincipal, + expectedPartner: goodPartner[0], + expectedEndpoint: urlStr, + }, + { + description: "Token Missing From Context Error", + errorOut: true, + emptyContext: true, + partnerIDs: goodPartner, + capabilities: goodCapabilities, + expectedOutcome: RejectedOutcome, + expectedReason: TokenMissing, + expectedErr: ErrNoAuth, + }, + { + description: "Token Missing From Context Accepted", + emptyContext: true, + partnerIDs: goodPartner, + capabilities: goodCapabilities, + expectedOutcome: AcceptedOutcome, + expectedReason: TokenMissing, + }, + { + description: "Prep Metrics Error", + errorOut: true, + partnerIDs: []int{5, 7, 11}, + capabilities: goodCapabilities, + expectedOutcome: RejectedOutcome, + expectedReason: UndeterminedPartnerID, + expectedClient: goodPrincipal, + expectedErr: errors.New("couldn't get partner IDs"), + }, + { + description: "Prep Metrics Accepted", + partnerIDs: []int{5, 7, 11}, + capabilities: goodCapabilities, + expectedOutcome: AcceptedOutcome, + expectedReason: UndeterminedPartnerID, + expectedClient: goodPrincipal, + }, + { + description: "Get Capabilities Error", + errorOut: true, + partnerIDs: goodPartner, + capabilities: []int{3, 1, 4}, + expectedOutcome: RejectedOutcome, + expectedReason: UndeterminedCapabilities, + expectedClient: goodPrincipal, + expectedPartner: goodPartner[0], + expectedEndpoint: urlStr, + expectedErr: errors.New("couldn't get capabilities"), + }, + { + description: "Get Capabilities Accepted", + partnerIDs: goodPartner, + capabilities: []int{3, 1, 4}, + expectedOutcome: AcceptedOutcome, + expectedReason: UndeterminedCapabilities, + expectedClient: goodPrincipal, + expectedPartner: goodPartner[0], + expectedEndpoint: urlStr, + }, + { + description: "Capability Check Error", + errorOut: true, + partnerIDs: goodPartner, + capabilities: []string{"failure"}, + expectedOutcome: RejectedOutcome, + expectedReason: NoCapabilitiesMatch, + expectedClient: goodPrincipal, + expectedPartner: goodPartner[0], + expectedEndpoint: urlStr, + expectedErr: ErrNoValidCapabilityFound, + }, + { + description: "Capability Check Accepted", + partnerIDs: goodPartner, + capabilities: []string{"failure"}, + expectedOutcome: AcceptedOutcome, + expectedReason: NoCapabilitiesMatch, + expectedClient: goodPrincipal, + expectedPartner: goodPartner[0], + expectedEndpoint: urlStr, + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + p := xmetricstest.NewProvider(nil, Metrics) + m := NewAuthCapabilityCheckMeasures(p) + + c, err := NewCapabilityChecker(m, "test:", "all") + assert.Nil(err) + + attrMap := map[string]interface{}{PartnerKey: tc.partnerIDs, CapabilityKey: tc.capabilities} + attrs := bascule.NewAttributesFromMap(attrMap) + auth := bascule.Authentication{ + Authorization: "TestAuthorization", + Token: bascule.NewToken("cool type", goodPrincipal, attrs), + Request: bascule.Request{ + URL: goodURL, + Method: "GET", + }, + } + ctx := context.Background() + if !tc.emptyContext { + ctx = bascule.WithAuthentication(ctx, auth) + } + + p.Assert(t, AuthCapabilityCheckOutcome)(xmetricstest.Value(0.0)) + check := c.CreateBasculeCheck(tc.errorOut) + err = check(ctx, auth.Token) + p.Assert(t, AuthCapabilityCheckOutcome, + OutcomeLabel, tc.expectedOutcome, + ReasonLabel, tc.expectedReason, + ClientIDLabel, tc.expectedClient, + PartnerIDLabel, tc.expectedPartner, + EndpointLabel, tc.expectedEndpoint, + )(xmetricstest.Counter, xmetricstest.Value(1.0)) + if err == nil || tc.expectedErr == nil { + assert.Equal(tc.expectedErr, err) + } else { + assert.Contains(err.Error(), tc.expectedErr.Error()) + } + }) + } } -func TestValidCapabilityCheck(t *testing.T) { - acceptAll := "all" - prefix := "a:b:c:" - check, err := CreateValidCapabilityCheck(prefix, acceptAll) - assert.Nil(t, err) - u, err := url.Parse("/test") - assert.Nil(t, err) - goodAuth := bascule.Authentication{ - Authorization: "jwt", - Token: bascule.NewToken("Bearer", "jwt", bascule.Attributes{}), - Request: bascule.Request{ - URL: u, - Method: "GET", +func TestNewCapabilityChecker(t *testing.T) { + tests := []struct { + description string + goodMeasures bool + prefix string + expectedErr error + }{ + { + description: "Success", + goodMeasures: true, + prefix: "testprefix:", + expectedErr: nil, + }, + { + description: "Nil Measures Error", + goodMeasures: false, + prefix: "", + expectedErr: errors.New("nil capability check measures"), + }, + { + description: "Bad Prefix Error", + goodMeasures: true, + prefix: `\K`, + expectedErr: errors.New("failed to compile prefix given"), }, } - goodContext := bascule.WithAuthentication(context.Background(), goodAuth) - goodVals := []interface{}{ + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + var m *AuthCapabilityCheckMeasures + if tc.goodMeasures { + p := xmetricstest.NewProvider(nil, Metrics) + m = NewAuthCapabilityCheckMeasures(p) + } + check, err := NewCapabilityChecker(m, tc.prefix, "all") + if err == nil || tc.expectedErr == nil { + assert.Equal(tc.expectedErr, err) + assert.NotNil(check) + } else { + assert.Contains(err.Error(), tc.expectedErr.Error()) + assert.Nil(check) + } + }) + } +} + +func TestCheckCapabilities(t *testing.T) { + goodURL, err := url.Parse("/test") + assert.Nil(t, err) + goodRequest := bascule.Request{ + URL: goodURL, + Method: "GET", + } + goodCapabilities := []string{ "d:e:f:/aaaa:post", - "a:b:d:/aaaa:all", + "a:b:d:/aaaa:allIn", `a:b:c:/test\b:post`, - `a:b:c:z:all`, + `a:b:c:z:allIn`, `a:b:c:/test\b:get`, } + badCapabilities := []string{ + "a:b:d:/aaaa:allIn", + `a:b:c:/test\b:post`, + } tests := []struct { - description string - ctx context.Context - vals []interface{} - expectedErr error + description string + capabilities []string + expectedErr error }{ { - description: "Success", - ctx: goodContext, - vals: goodVals, + description: "Success", + capabilities: goodCapabilities, + expectedErr: nil, }, { - description: "No Vals Error", - expectedErr: ErrNoVals, + description: "No Capabilities Error", + capabilities: []string{}, + expectedErr: ErrNoValidCapabilityFound, }, { - description: "No Auth Error", - ctx: context.Background(), - vals: goodVals, - expectedErr: ErrNoAuth, + description: "No Matching Capabilities Error", + capabilities: badCapabilities, + expectedErr: ErrNoValidCapabilityFound, }, + } + p := xmetricstest.NewProvider(nil, Metrics) + m := NewAuthCapabilityCheckMeasures(p) + c, err := NewCapabilityChecker(m, "a:b:c:", "allIn") + assert.Nil(t, err) + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + err := c.checkCapabilities(tc.capabilities, goodRequest) + if err == nil || tc.expectedErr == nil { + assert.Equal(tc.expectedErr, err) + } else { + assert.Contains(err.Error(), tc.expectedErr.Error()) + } + }) + } +} + +func TestPrepMetrics(t *testing.T) { + goodURL := "/asnkfn/aefkijeoij/aiogj" + matchingURL := "/fnvvdsjkfji/mac:12345544322345334/geigosj" + abridgedURL := "/fnvvdsjkfji/.../geigosj" + client := "special" + prepErr := errors.New("couldn't get partner IDs from attributes") + tests := []struct { + description string + noPartnerID bool + partnerIDs interface{} + url string + expectedPartner string + expectedEndpoint string + expectedReason string + expectedErr error + }{ { - description: "Nonstring Val Error", - ctx: goodContext, - vals: []interface{}{3}, - expectedErr: ErrNonstringVal, + description: "Success", + partnerIDs: []string{"partner"}, + url: goodURL, + expectedPartner: "partner", + expectedEndpoint: goodURL, + expectedReason: "", + expectedErr: nil, }, { - description: "No Valid Capability Error", - ctx: goodContext, - vals: []interface{}{"::::"}, - expectedErr: ErrNoValidCapabilityFound, + description: "Success Abridged URL", + partnerIDs: []string{"partner"}, + url: matchingURL, + expectedPartner: "partner", + expectedEndpoint: abridgedURL, + expectedReason: "", + expectedErr: nil, + }, + { + description: "No Partner ID Error", + noPartnerID: true, + url: goodURL, + expectedPartner: "", + expectedEndpoint: "", + expectedReason: UndeterminedPartnerID, + expectedErr: prepErr, + }, + { + description: "Non String Slice Partner ID Error", + partnerIDs: []int{0, 1, 2}, + url: goodURL, + expectedPartner: "", + expectedEndpoint: "", + expectedReason: UndeterminedPartnerID, + expectedErr: prepErr, + }, + { + description: "Non Slice Partner ID Error", + partnerIDs: struct{ string }{}, + url: goodURL, + expectedPartner: "", + expectedEndpoint: "", + expectedReason: UndeterminedPartnerID, + expectedErr: prepErr, }, } + p := xmetricstest.NewProvider(nil, Metrics) + m := NewAuthCapabilityCheckMeasures(p) + c, err := NewCapabilityChecker(m, "prefix:", "all") + assert.Nil(t, err) + for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - err := check(tc.ctx, tc.vals) - if tc.expectedErr == nil || err == nil { + u, err := url.ParseRequestURI(tc.url) + assert.Nil(err) + m := map[string]interface{}{} + if !tc.noPartnerID { + m[PartnerKey] = tc.partnerIDs + } + attributes := bascule.NewAttributesFromMap(m) + auth := bascule.Authentication{ + Authorization: "testAuth", + Token: bascule.NewToken("mehType", client, attributes), + Request: bascule.Request{ + URL: u, + Method: "get", + }, + } + c, partner, endpoint, reason, err := c.prepMetrics(auth) + assert.Equal(client, c) + assert.Equal(tc.expectedPartner, partner) + assert.Equal(tc.expectedEndpoint, endpoint) + assert.Equal(tc.expectedReason, reason) + if err == nil || tc.expectedErr == nil { + assert.Equal(tc.expectedErr, err) + } else { + assert.Contains(err.Error(), tc.expectedErr.Error()) + } + }) + } +} + +func TestDeterminePartnerMetric(t *testing.T) { + tests := []struct { + description string + partnersInput []string + expectedResult string + }{ + { + description: "No Partners", + expectedResult: "none", + }, + { + description: "one wildcard", + partnersInput: []string{"*"}, + expectedResult: "wildcard", + }, + { + description: "one partner", + partnersInput: []string{"TestPartner"}, + expectedResult: "TestPartner", + }, + { + description: "many partners", + partnersInput: []string{"partner1", "partner2", "partner3"}, + expectedResult: "many", + }, + { + description: "many partners with wildcard", + partnersInput: []string{"partner1", "partner2", "partner3", "*"}, + expectedResult: "wildcard", + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + partner := determinePartnerMetric(tc.partnersInput) + assert.Equal(tc.expectedResult, partner) + }) + } +} + +func TestGetCapabilities(t *testing.T) { + goodKeyVal := []string{"cap1", "cap2"} + emptyVal := []string{} + getCapabilitiesErr := errors.New("couldn't get capabilities using key") + tests := []struct { + description string + nilAttributes bool + missingAttribute bool + keyValue interface{} + expectedVals []string + expectedReason string + expectedErr error + }{ + { + description: "Success", + keyValue: goodKeyVal, + expectedVals: goodKeyVal, + expectedReason: "", + expectedErr: nil, + }, + { + description: "Nil Attributes Error", + nilAttributes: true, + expectedVals: emptyVal, + expectedReason: UndeterminedCapabilities, + expectedErr: ErrNilAttributes, + }, + { + description: "No Attribute Error", + missingAttribute: true, + expectedVals: emptyVal, + expectedReason: UndeterminedCapabilities, + expectedErr: getCapabilitiesErr, + }, + { + description: "Nil Capabilities Error", + keyValue: nil, + expectedVals: emptyVal, + expectedReason: UndeterminedCapabilities, + expectedErr: getCapabilitiesErr, + }, + { + description: "Non List Capabilities Error", + keyValue: struct{ string }{"abcd"}, + expectedVals: emptyVal, + expectedReason: UndeterminedCapabilities, + expectedErr: getCapabilitiesErr, + }, + { + description: "Non String List Capabilities Error", + keyValue: []int{0, 1, 2}, + expectedVals: emptyVal, + expectedReason: UndeterminedCapabilities, + expectedErr: getCapabilitiesErr, + }, + { + description: "Empty Capabilities Error", + keyValue: emptyVal, + expectedVals: emptyVal, + expectedReason: EmptyCapabilitiesList, + expectedErr: ErrNoVals, + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + m := map[string]interface{}{CapabilityKey: tc.keyValue} + if tc.missingAttribute { + m = map[string]interface{}{} + } + attributes := bascule.NewAttributesFromMap(m) + if tc.nilAttributes { + attributes = nil + } + vals, reason, err := getCapabilities(attributes) + assert.Equal(tc.expectedVals, vals) + assert.Equal(tc.expectedReason, reason) + if err == nil || tc.expectedErr == nil { assert.Equal(tc.expectedErr, err) } else { assert.Contains(err.Error(), tc.expectedErr.Error()) diff --git a/basculechecks/metrics.go b/basculechecks/metrics.go index eb73d956..4a1638c2 100644 --- a/basculechecks/metrics.go +++ b/basculechecks/metrics.go @@ -2,58 +2,56 @@ package basculechecks import ( "github.com/go-kit/kit/metrics" - gokitprometheus "github.com/go-kit/kit/metrics/prometheus" + "github.com/go-kit/kit/metrics/provider" "github.com/xmidt-org/webpa-common/xmetrics" ) //Names for our metrics const ( - JWTValidationReasonCounter = "jwt_validation_reason" - NBFHistogram = "jwt_from_nbf_seconds" - EXPHistogram = "jwt_from_exp_seconds" + AuthCapabilityCheckOutcome = "auth_capability_check" ) // labels const ( - ReasonLabel = "reason" + OutcomeLabel = "outcome" + ReasonLabel = "reason" + ClientIDLabel = "clientid" + EndpointLabel = "endpoint" + PartnerIDLabel = "partnerid" +) + +// outcomes +const ( + RejectedOutcome = "rejected" + AcceptedOutcome = "accepted" + // reasons + TokenMissing = "auth_missing" + UndeterminedPartnerID = "undetermined_partner_ID" + UndeterminedCapabilities = "undetermined_capabilities" + EmptyCapabilitiesList = "empty_capabilities_list" + NoCapabilitiesMatch = "no_capabilities_match" ) //Metrics returns the Metrics relevant to this package func Metrics() []xmetrics.Metric { return []xmetrics.Metric{ xmetrics.Metric{ - Name: JWTValidationReasonCounter, + Name: AuthCapabilityCheckOutcome, Type: xmetrics.CounterType, - Help: "Counter for validation resolutions per reason", - LabelNames: []string{ReasonLabel}, - }, - xmetrics.Metric{ - Name: NBFHistogram, - Type: xmetrics.HistogramType, - Help: "Difference (in seconds) between time of JWT validation and nbf (including leeway)", - Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, // defines the upper inclusive (<=) bounds - }, - xmetrics.Metric{ - Name: EXPHistogram, - Type: xmetrics.HistogramType, - Help: "Difference (in seconds) between time of JWT validation and exp (including leeway)", - Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, + Help: "Counter for the capability checker, providing outcome information by client, partner, and endpoint", + LabelNames: []string{OutcomeLabel, ReasonLabel, ClientIDLabel, PartnerIDLabel, EndpointLabel}, }, } } -//JWTValidationMeasures describes the defined metrics that will be used by clients -type JWTValidationMeasures struct { - NBFHistogram *gokitprometheus.Histogram - ExpHistogram *gokitprometheus.Histogram - ValidationReason metrics.Counter +//AuthCapabilityCheckMeasures describes the defined metrics that will be used by clients +type AuthCapabilityCheckMeasures struct { + CapabilityCheckOutcome metrics.Counter } -//NewJWTValidationMeasures realizes desired metrics -func NewJWTValidationMeasures(r xmetrics.Registry) *JWTValidationMeasures { - return &JWTValidationMeasures{ - NBFHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(NBFHistogram)), - ExpHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(EXPHistogram)), - ValidationReason: r.NewCounter(JWTValidationReasonCounter), +//NewAuthCapabilityCheckMeasures realizes desired metrics +func NewAuthCapabilityCheckMeasures(p provider.Provider) *AuthCapabilityCheckMeasures { + return &AuthCapabilityCheckMeasures{ + CapabilityCheckOutcome: p.NewCounter(AuthCapabilityCheckOutcome), } } diff --git a/basculechecks/metrics_test.go b/basculechecks/metrics_test.go index 4218bdba..2f5dcdd1 100644 --- a/basculechecks/metrics_test.go +++ b/basculechecks/metrics_test.go @@ -7,11 +7,11 @@ import ( "github.com/xmidt-org/webpa-common/xmetrics" ) -func newTestJWTValidationMeasure() *JWTValidationMeasures { - return NewJWTValidationMeasures(xmetrics.MustNewRegistry(nil, Metrics)) +func newTestAuthCapabilityCheckMeasure() *AuthCapabilityCheckMeasures { + return NewAuthCapabilityCheckMeasures(xmetrics.MustNewRegistry(nil, Metrics)) } func TestSimpleRun(t *testing.T) { assert := assert.New(t) - assert.NotNil(newTestJWTValidationMeasure()) + assert.NotNil(newTestAuthCapabilityCheckMeasure()) } diff --git a/basculechecks/metricListener.go b/basculemetrics/metricListener.go similarity index 85% rename from basculechecks/metricListener.go rename to basculemetrics/metricListener.go index ed2ad843..8919dea5 100644 --- a/basculechecks/metricListener.go +++ b/basculemetrics/metricListener.go @@ -1,4 +1,4 @@ -package basculechecks +package basculemetrics import ( "time" @@ -11,7 +11,7 @@ import ( type MetricListener struct { expLeeway time.Duration nbfLeeway time.Duration - measures *JWTValidationMeasures + measures *AuthValidationMeasures } func (m *MetricListener) OnAuthenticated(auth bascule.Authentication) { @@ -25,6 +25,8 @@ func (m *MetricListener) OnAuthenticated(auth bascule.Authentication) { return } + m.measures.ValidationOutcome.With(OutcomeLabel, "Accepted").Add(1) + c, ok := auth.Token.Attributes().Get("claims") if !ok { return // if there aren't any claims, skip @@ -53,7 +55,7 @@ func (m *MetricListener) OnErrorResponse(e basculehttp.ErrorResponseReason, _ er if m.measures == nil { return } - m.measures.ValidationReason.With(ReasonLabel, e.String()).Add(1) + m.measures.ValidationOutcome.With(OutcomeLabel, e.String()).Add(1) } type Option func(m *MetricListener) @@ -70,7 +72,7 @@ func WithNbfLeeway(n time.Duration) Option { } } -func NewMetricListener(m *JWTValidationMeasures, options ...Option) *MetricListener { +func NewMetricListener(m *AuthValidationMeasures, options ...Option) *MetricListener { listener := MetricListener{ measures: m, } diff --git a/basculemetrics/metrics.go b/basculemetrics/metrics.go new file mode 100644 index 00000000..2af439bc --- /dev/null +++ b/basculemetrics/metrics.go @@ -0,0 +1,59 @@ +package basculemetrics + +import ( + "github.com/go-kit/kit/metrics" + gokitprometheus "github.com/go-kit/kit/metrics/prometheus" + "github.com/xmidt-org/webpa-common/xmetrics" +) + +//Names for our metrics +const ( + AuthValidationOutcome = "auth_validation" + NBFHistogram = "auth_from_nbf_seconds" + EXPHistogram = "auth_from_exp_seconds" +) + +// labels +const ( + OutcomeLabel = "outcome" +) + +//Metrics returns the Metrics relevant to this package +func Metrics() []xmetrics.Metric { + return []xmetrics.Metric{ + xmetrics.Metric{ + Name: AuthValidationOutcome, + Type: xmetrics.CounterType, + Help: "Counter for success and failure reason results through bascule", + LabelNames: []string{OutcomeLabel}, + }, + xmetrics.Metric{ + Name: NBFHistogram, + Type: xmetrics.HistogramType, + Help: "Difference (in seconds) between time of JWT validation and nbf (including leeway)", + Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, // defines the upper inclusive (<=) bounds + }, + xmetrics.Metric{ + Name: EXPHistogram, + Type: xmetrics.HistogramType, + Help: "Difference (in seconds) between time of JWT validation and exp (including leeway)", + Buckets: []float64{-61, -11, -2, -1, 0, 9, 60}, + }, + } +} + +//AuthValidationMeasures describes the defined metrics that will be used by clients +type AuthValidationMeasures struct { + NBFHistogram *gokitprometheus.Histogram + ExpHistogram *gokitprometheus.Histogram + ValidationOutcome metrics.Counter +} + +//NewAuthValidationMeasures realizes desired metrics +func NewAuthValidationMeasures(r xmetrics.Registry) *AuthValidationMeasures { + return &AuthValidationMeasures{ + NBFHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(NBFHistogram)), + ExpHistogram: gokitprometheus.NewHistogram(r.NewHistogramVec(EXPHistogram)), + ValidationOutcome: r.NewCounter(AuthValidationOutcome), + } +} diff --git a/basculemetrics/metrics_test.go b/basculemetrics/metrics_test.go new file mode 100644 index 00000000..8b31b7ec --- /dev/null +++ b/basculemetrics/metrics_test.go @@ -0,0 +1,17 @@ +package basculemetrics + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/xmidt-org/webpa-common/xmetrics" +) + +func newTestAuthValidationMeasure() *AuthValidationMeasures { + return NewAuthValidationMeasures(xmetrics.MustNewRegistry(nil, Metrics)) +} + +func TestSimpleRun(t *testing.T) { + assert := assert.New(t) + assert.NotNil(newTestAuthValidationMeasure()) +} diff --git a/go.mod b/go.mod index 0f1ecbd5..a5eaf3d0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/xmidt-org/webpa-common go 1.13 require ( - github.com/BurntSushi/toml v0.3.1 // indirect github.com/GaryBoone/GoStats v0.0.0-20130122001700-1993eafbef57 // indirect github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 github.com/VividCortex/gohistogram v1.0.0 // indirect @@ -16,10 +15,9 @@ require ( github.com/go-ini/ini v1.36.1-0.20180420150025-bda519ae5f4c // indirect github.com/go-kit/kit v0.8.0 github.com/goph/emperror v0.17.3-0.20190703203600-60a8d9faa17b - github.com/gorilla/context v1.1.1 // indirect - github.com/gorilla/mux v1.6.1 + github.com/gorilla/mux v1.7.3 github.com/gorilla/schema v1.0.3-0.20180614150749-e0e4b92809ac - github.com/gorilla/websocket v1.2.0 + github.com/gorilla/websocket v1.4.0 github.com/hashicorp/consul v1.4.2 github.com/hashicorp/go-cleanhttp v0.5.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect @@ -29,24 +27,21 @@ require ( github.com/influxdata/influxdb v1.5.1-0.20180921190457-8d679cf0c36e // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/jtacoma/uritemplates v1.0.0 - github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da + github.com/justinas/alice v1.2.0 github.com/miekg/dns v1.0.14 github.com/mitchellh/go-homedir v1.0.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/pascaldekloe/goe v0.1.0 // indirect github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea // indirect github.com/pkg/errors v0.8.1-0.20181008045315-2233dee583dc // indirect - github.com/prometheus/client_golang v0.9.2 + github.com/prometheus/client_golang v0.9.3 github.com/rubyist/circuitbreaker v2.2.0+incompatible github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect - github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670 // indirect github.com/spf13/pflag v1.0.3 - github.com/spf13/viper v1.3.1 + github.com/spf13/viper v1.6.1 github.com/stretchr/testify v1.3.0 github.com/ugorji/go/codec v1.1.7 - github.com/xmidt-org/bascule v0.7.0 + github.com/xmidt-org/bascule v0.8.0 github.com/xmidt-org/wrp-go v1.3.3 - gopkg.in/ini.v1 v1.46.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 + gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) diff --git a/go.sum b/go.sum index dcf732f7..b30ce470 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,16 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GaryBoone/GoStats v0.0.0-20130122001700-1993eafbef57 h1:EUQH/F+mzJBs53c75r7R5zdM/kz7BHXoWBFsVXzadVw= github.com/GaryBoone/GoStats v0.0.0-20130122001700-1993eafbef57/go.mod h1:5zDl2HgTb/k5i9op9y6IUSiuVkZFpUrWGQbZc9tNR40= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 h1:koK7z0nSsRiRiBWwa+E714Puh+DO+ZRdIyAXiXzL+lg= github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/airbrake/gobrake v3.6.1+incompatible/go.mod h1:wM4gu3Cn0W0K7GUuVWnlXZU11AGBXMILnrdOU8Kn00o= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -14,6 +18,8 @@ github.com/aws/aws-sdk-go v1.8.12 h1:b0fXUoyobc5gJPWDLILKg7wZQFhWFS9IgyopMYIHEv8 github.com/aws/aws-sdk-go v1.8.12/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/billhathaway/consistentHash v0.0.0-20140718022140-addea16d2229 h1:w1t+UCLwxXgpUcXAlm3IkvWHGJDfhIyNrzJmCUkJq7s= github.com/billhathaway/consistentHash v0.0.0-20140718022140-addea16d2229/go.mod h1:YTos5xiYv+RiIsYn3pqdwe5OULySucMqiPes1OgC5pM= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= @@ -25,20 +31,26 @@ github.com/c9s/goprocinfo v0.0.0-20151025191153-19cb9f127a9c/go.mod h1:uEyr4WpAH github.com/cenk/backoff v2.0.0+incompatible h1:7vXVw3g7XE+Vnj0A9TmFGtMeP4oZQ5ZzpPvKhLFa80E= github.com/cenk/backoff v2.0.0+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1-0.20171005155431-ecdeabc65495/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 h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 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/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-ini/ini v1.36.1-0.20180420150025-bda519ae5f4c h1:/fXq3T13myi/yMip3083tbcob0FiQ2cbnAEW9YmZp8E= github.com/go-ini/ini v1.36.1-0.20180420150025-bda519ae5f4c/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= @@ -49,23 +61,34 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= 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/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/goph/emperror v0.17.1/go.mod h1:+ZbQ+fUNO/6FNiUo0ujtMjhgad9Xa6fQL9KhH4LNHic= github.com/goph/emperror v0.17.3-0.20190703203600-60a8d9faa17b h1:3/cwc6wu5QADzKEW2HP7+kZpKgm7OHysQ3ULVVQzQhs= github.com/goph/emperror v0.17.3-0.20190703203600-60a8d9faa17b/go.mod h1:+ZbQ+fUNO/6FNiUo0ujtMjhgad9Xa6fQL9KhH4LNHic= 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/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A= -github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/schema v1.0.3-0.20180614150749-e0e4b92809ac h1:bKzUNrDAqmZRmpeWm7jpGLCvpkESi4zchWBMbtf6Mzk= github.com/gorilla/schema v1.0.3-0.20180614150749-e0e4b92809ac/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= -github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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/hashicorp/consul v1.4.2 h1:D9iJoJb8Ehe/Zmr+UEE3U3FjOLZ4LUxqFMl4O43BM1U= github.com/hashicorp/consul v1.4.2/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -98,21 +121,27 @@ github.com/influxdata/influxdb v1.5.1-0.20180921190457-8d679cf0c36e h1:Ai8OUa/B9 github.com/influxdata/influxdb v1.5.1-0.20180921190457-8d679cf0c36e/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= 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/jtacoma/uritemplates v1.0.0 h1:xwx5sBF7pPAb0Uj8lDC1Q/aBPpOFyQza7OC705ZlLCo= github.com/jtacoma/uritemplates v1.0.0/go.mod h1:IhIICdE9OcvgUnGwTtJxgBQ+VrTrti5PcbLVSJianO8= 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/justinas/alice v0.0.0-20171023064455-03f45bd4b7da h1:5y58+OCjoHCYB8182mpf/dEsq0vwTKPOo4zGfH0xW9A= -github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da/go.mod h1:oLH0CmIaxCGXD67VKGR5AacGXZSMznlmeqM8RzPrcY8= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= +github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= @@ -123,6 +152,8 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -138,14 +169,21 @@ github.com/pkg/errors v0.8.1-0.20181008045315-2233dee583dc h1:pYfn3vMvdjwZHla4XX github.com/pkg/errors v0.8.1-0.20181008045315-2233dee583dc/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ= github.com/rubyist/circuitbreaker v2.2.0+incompatible h1:/v/ynV/XTY3rl2ESDuRZvJw2mjXdlhAYRs+KNfqRYeg= github.com/rubyist/circuitbreaker v2.2.0+incompatible/go.mod h1:Ycs3JgJADPuzJDwffe12k6BZT8hxVi6lFK+gWYJLN4A= @@ -156,10 +194,11 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg 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 v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670 h1:hKP4ACPoBBCnBbhoiuJXiYlSDhAvC9s4lgzAPmtVdU0= -github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= @@ -168,8 +207,8 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38= -github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= 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.1.2-0.20180825064932-ef50b0de2877 h1:6K1nYEj5Y6jqgsc/SWBuF7YcLqaQbWSNAmf4LtApioo= @@ -178,54 +217,80 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +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= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/xmidt-org/bascule v0.7.0 h1:TUbSKq68CzutTXYh5hq8mhMCHeYdIXaUffx3qCMo1yE= -github.com/xmidt-org/bascule v0.7.0/go.mod h1:D2DuXSMa5+OpveCtaSWp0+/tmnxZqfYhkCC1oCzLZdI= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xmidt-org/bascule v0.8.0 h1:xk/c8zqqNjoSW4b4oSrUwemm786Bs5DabmX7AgUgNPw= +github.com/xmidt-org/bascule v0.8.0/go.mod h1:dPxlbNT3lCwYAtOq2zbzyzTEKgM+azLSbKKcVmgSHBY= github.com/xmidt-org/webpa-common v1.1.0/go.mod h1:oCpKzOC+9h2vYHVzAU/06tDTQuBN4RZz+rhgIXptpOI= github.com/xmidt-org/webpa-common v1.3.1/go.mod h1:oCpKzOC+9h2vYHVzAU/06tDTQuBN4RZz+rhgIXptpOI= github.com/xmidt-org/wrp-go v1.3.3 h1:WvODdrtxPwHEUqwfwHpu+kNUfBzLBfAIdrKCQjoCblc= github.com/xmidt-org/wrp-go v1.3.3/go.mod h1:VOKYeeVWc2cyYmGWJksqUCV/lGzReRl0EP74y3mcWp0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag= -gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI= -gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +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/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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=