diff --git a/charts/consul/templates/crd-routeauthfilters.yaml b/charts/consul/templates/crd-routeauthfilters.yaml index cd4ac4257d..5905716614 100644 --- a/charts/consul/templates/crd-routeauthfilters.yaml +++ b/charts/consul/templates/crd-routeauthfilters.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: routeauthfilters.consul.hashicorp.com labels: @@ -56,26 +56,40 @@ spec: description: RouteAuthFilterSpec defines the desired state of RouteAuthFilter. properties: jwt: - description: RouteJWTRequirement defines the JWT requirements per - provider. + description: This re-uses the JWT requirement type from Gateway Policy + Types. properties: providers: + description: Providers is a list of providers to consider when + verifying a JWT. items: - description: RouteJWTProvider defines the configuration for - a specific JWT provider. + description: GatewayJWTProvider holds the provider and claim + verification information. properties: name: + description: Name is the name of the JWT provider. There + MUST be a corresponding "jwt-provider" config entry with + this name. type: string verifyClaims: + description: VerifyClaims is a list of additional claims + to verify in a JWT's payload. items: - description: RouteJWTClaimVerification defines the specific - claims to be verified. + description: GatewayJWTClaimVerification holds the actual + claim information to be verified. properties: path: + description: Path is the path to the claim in the + token JSON. items: type: string type: array value: + description: "Value is the expected value at the given + path: - If the type at the path is a list then we + verify that this value is contained in the list. + \n - If the type at the path is a string then we + verify that this value matches." type: string required: - path @@ -84,7 +98,6 @@ spec: type: array required: - name - - verifyClaims type: object type: array required: @@ -134,4 +147,10 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] {{- end }} diff --git a/control-plane/api-gateway/common/translation.go b/control-plane/api-gateway/common/translation.go index 961ecb9d5c..d99600795c 100644 --- a/control-plane/api-gateway/common/translation.go +++ b/control-plane/api-gateway/common/translation.go @@ -147,6 +147,32 @@ func ToContainerPort(portNumber gwv1beta1.PortNumber, mapPrivilegedContainerPort return int(portNumber) + int(mapPrivilegedContainerPorts) } +func (t ResourceTranslator) translateRouteRetryFilter(routeRetryFilter *v1alpha1.RouteRetryFilter) *api.RetryFilter { + return &api.RetryFilter{ + NumRetries: routeRetryFilter.Spec.NumRetries, + RetryOn: routeRetryFilter.Spec.RetryOn, + RetryOnStatusCodes: routeRetryFilter.Spec.RetryOnStatusCodes, + RetryOnConnectFailure: routeRetryFilter.Spec.RetryOnConnectFailure, + } +} + +func (t ResourceTranslator) translateRouteTimeoutFilter(routeTimeoutFilter *v1alpha1.RouteTimeoutFilter) *api.TimeoutFilter { + return &api.TimeoutFilter{ + RequestTimeout: routeTimeoutFilter.Spec.RequestTimeout, + IdleTimeout: routeTimeoutFilter.Spec.IdleTimeout, + } +} + +func (t ResourceTranslator) translateRouteJWTFilter(routeJWTFilter *v1alpha1.RouteAuthFilter) *api.JWTFilter { + if routeJWTFilter.Spec.JWT == nil { + return nil + } + + return &api.JWTFilter{ + Providers: ConvertSliceFunc(routeJWTFilter.Spec.JWT.Providers, t.translateJWTProvider), + } +} + func (t ResourceTranslator) translateGatewayPolicy(policy *v1alpha1.GatewayPolicy) (*api.APIGatewayPolicy, *api.APIGatewayPolicy) { if policy == nil { return nil, nil @@ -204,12 +230,14 @@ func (t ResourceTranslator) translateVerifyClaims(crdClaims *v1alpha1.GatewayJWT func (t ResourceTranslator) ToHTTPRoute(route gwv1beta1.HTTPRoute, resources *ResourceMap) *api.HTTPRouteConfigEntry { namespace := t.Namespace(route.Namespace) - // we don't translate parent refs + // We don't translate parent refs. hostnames := StringLikeSlice(route.Spec.Hostnames) - rules := ConvertSliceFuncIf(route.Spec.Rules, func(rule gwv1beta1.HTTPRouteRule) (api.HTTPRouteRule, bool) { - return t.translateHTTPRouteRule(route, rule, resources) - }) + rules := ConvertSliceFuncIf( + route.Spec.Rules, + func(rule gwv1beta1.HTTPRouteRule) (api.HTTPRouteRule, bool) { + return t.translateHTTPRouteRule(route, rule, resources) + }) configEntry := api.HTTPRouteConfigEntry{ Kind: api.HTTPRoute, @@ -228,10 +256,11 @@ func (t ResourceTranslator) ToHTTPRoute(route gwv1beta1.HTTPRoute, resources *Re } func (t ResourceTranslator) translateHTTPRouteRule(route gwv1beta1.HTTPRoute, rule gwv1beta1.HTTPRouteRule, resources *ResourceMap) (api.HTTPRouteRule, bool) { - services := ConvertSliceFuncIf(rule.BackendRefs, func(ref gwv1beta1.HTTPBackendRef) (api.HTTPService, bool) { - - return t.translateHTTPBackendRef(route, ref, resources) - }) + services := ConvertSliceFuncIf( + rule.BackendRefs, + func(ref gwv1beta1.HTTPBackendRef) (api.HTTPService, bool) { + return t.translateHTTPBackendRef(route, ref, resources) + }) if len(services) == 0 { return api.HTTPRouteRule{}, false @@ -336,13 +365,18 @@ func (t ResourceTranslator) translateHTTPQueryMatch(match gwv1beta1.HTTPQueryPar } func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFilter, resourceMap *ResourceMap, namespace string) api.HTTPFilters { - var urlRewrite *api.URLRewrite + var ( + // Each of these variables will have just one possible value at the end of the function. + urlRewrite *api.URLRewrite + retryFilter *api.RetryFilter + timeoutFilter *api.TimeoutFilter + jwtFilter *api.JWTFilter + ) + consulFilter := api.HTTPHeaderFilter{ Add: make(map[string]string), Set: make(map[string]string), } - var retryFilter *api.RetryFilter - var timeoutFilter *api.TimeoutFilter for _, filter := range filters { if filter.RequestHeaderModifier != nil { @@ -371,38 +405,24 @@ func (t ResourceTranslator) translateHTTPFilters(filters []gwv1beta1.HTTPRouteFi // this should never be the case because we only translate a route if it's actually valid, and if we're missing filters during the validation step, then we won't get here continue } + switch filter.ExtensionRef.Kind { case v1alpha1.RouteRetryFilterKind: - - retryFilterCRD := crdFilter.(*v1alpha1.RouteRetryFilter) - //new filter that needs to be appended - - retryFilter = &api.RetryFilter{ - NumRetries: retryFilterCRD.Spec.NumRetries, - RetryOn: retryFilterCRD.Spec.RetryOn, - RetryOnStatusCodes: retryFilterCRD.Spec.RetryOnStatusCodes, - RetryOnConnectFailure: retryFilterCRD.Spec.RetryOnConnectFailure, - } - + retryFilter = t.translateRouteRetryFilter(crdFilter.(*v1alpha1.RouteRetryFilter)) case v1alpha1.RouteTimeoutFilterKind: - - timeoutFilterCRD := crdFilter.(*v1alpha1.RouteTimeoutFilter) - //new filter that needs to be appended - - timeoutFilter = &api.TimeoutFilter{ - RequestTimeout: timeoutFilterCRD.Spec.RequestTimeout, - IdleTimeout: timeoutFilterCRD.Spec.IdleTimeout, - } - + timeoutFilter = t.translateRouteTimeoutFilter(crdFilter.(*v1alpha1.RouteTimeoutFilter)) + case v1alpha1.RouteAuthFilterKind: + jwtFilter = t.translateRouteJWTFilter(crdFilter.(*v1alpha1.RouteAuthFilter)) } } - } + return api.HTTPFilters{ Headers: []api.HTTPHeaderFilter{consulFilter}, URLRewrite: urlRewrite, RetryFilter: retryFilter, TimeoutFilter: timeoutFilter, + JWT: jwtFilter, } } diff --git a/control-plane/api-gateway/common/translation_test.go b/control-plane/api-gateway/common/translation_test.go index 2c7ff7e4cb..9265518581 100644 --- a/control-plane/api-gateway/common/translation_test.go +++ b/control-plane/api-gateway/common/translation_test.go @@ -10,13 +10,14 @@ import ( "crypto/x509/pkix" "encoding/pem" "fmt" - "k8s.io/utils/pointer" "math/big" - "sigs.k8s.io/controller-runtime/pkg/client" "strings" "testing" "time" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -1267,7 +1268,21 @@ func TestTranslator_ToHTTPRoute(t *testing.T) { ExtensionRef: &gwv1beta1.LocalObjectReference{ Name: "test", Kind: v1alpha1.RouteRetryFilterKind, - Group: "consul.hashicorp.com/v1alpha1", + Group: gwv1beta1.Group(v1alpha1.GroupVersion.Group), + }, + }, + { + ExtensionRef: &gwv1beta1.LocalObjectReference{ + Name: "test-timeout-filter", + Kind: v1alpha1.RouteTimeoutFilterKind, + Group: gwv1beta1.Group(v1alpha1.GroupVersion.Group), + }, + }, + { + ExtensionRef: &gwv1beta1.LocalObjectReference{ + Name: "test-jwt-filter", + Kind: v1alpha1.RouteAuthFilterKind, + Group: gwv1beta1.Group(v1alpha1.GroupVersion.Group), }, }, }, @@ -1332,6 +1347,47 @@ func TestTranslator_ToHTTPRoute(t *testing.T) { RetryOnConnectFailure: pointer.Bool(true), }, }, + + &v1alpha1.RouteTimeoutFilter{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.RouteTimeoutFilterKind, + APIVersion: "consul.hashicorp.com/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-timeout-filter", + Namespace: "k8s-ns", + }, + Spec: v1alpha1.RouteTimeoutFilterSpec{ + RequestTimeout: 10, + IdleTimeout: 30, + }, + }, + + &v1alpha1.RouteAuthFilter{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.RouteAuthFilterKind, + APIVersion: "consul.hashicorp.com/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-jwt-filter", + Namespace: "k8s-ns", + }, + Spec: v1alpha1.RouteAuthFilterSpec{ + JWT: &v1alpha1.GatewayJWTRequirement{ + Providers: []*v1alpha1.GatewayJWTProvider{ + { + Name: "test-jwt-provider", + VerifyClaims: []*v1alpha1.GatewayJWTClaimVerification{ + { + Path: []string{"/okta"}, + Value: "okta", + }, + }, + }, + }, + }, + }, + }, }, }, want: api.HTTPRouteConfigEntry{ @@ -1348,6 +1404,23 @@ func TestTranslator_ToHTTPRoute(t *testing.T) { RetryOnStatusCodes: []uint32{500, 502}, RetryOnConnectFailure: pointer.Bool(false), }, + TimeoutFilter: &api.TimeoutFilter{ + RequestTimeout: time.Duration(10 * time.Nanosecond), + IdleTimeout: time.Duration(30 * time.Nanosecond), + }, + JWT: &api.JWTFilter{ + Providers: []*api.APIGatewayJWTProvider{ + { + Name: "test-jwt-provider", + VerifyClaims: []*api.APIGatewayJWTClaimVerification{ + { + Path: []string{"/okta"}, + Value: "okta", + }, + }, + }, + }, + }, }, Matches: []api.HTTPMatch{ { diff --git a/control-plane/api/v1alpha1/routeauthfilter_types.go b/control-plane/api/v1alpha1/routeauthfilter_types.go index 3744ad533a..79f05399e6 100644 --- a/control-plane/api/v1alpha1/routeauthfilter_types.go +++ b/control-plane/api/v1alpha1/routeauthfilter_types.go @@ -7,6 +7,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + RouteAuthFilterKind = "RouteAuthFilter" +) + func init() { SchemeBuilder.Register(&RouteAuthFilter{}, &RouteAuthFilterList{}) } @@ -37,23 +41,7 @@ type RouteAuthFilterList struct { // RouteAuthFilterSpec defines the desired state of RouteAuthFilter. type RouteAuthFilterSpec struct { + // This re-uses the JWT requirement type from Gateway Policy Types. //+kubebuilder:validation:Optional - JWT *RouteJWTRequirement `json:"jwt,omitempty"` -} - -// RouteJWTRequirement defines the JWT requirements per provider. -type RouteJWTRequirement struct { - Providers []RouteJWTProvider `json:"providers"` -} - -// RouteJWTProvider defines the configuration for a specific JWT provider. -type RouteJWTProvider struct { - Name string `json:"name"` - VerifyClaims []RouteJWTClaimVerification `json:"verifyClaims"` -} - -// RouteJWTClaimVerification defines the specific claims to be verified. -type RouteJWTClaimVerification struct { - Path []string `json:"path"` - Value string `json:"value"` + JWT *GatewayJWTRequirement `json:"jwt,omitempty"` } diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index 5d8b0d2da3..6d75d3f692 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -2402,7 +2402,7 @@ func (in *RouteAuthFilterSpec) DeepCopyInto(out *RouteAuthFilterSpec) { *out = *in if in.JWT != nil { in, out := &in.JWT, &out.JWT - *out = new(RouteJWTRequirement) + *out = new(GatewayJWTRequirement) (*in).DeepCopyInto(*out) } } @@ -2417,70 +2417,6 @@ func (in *RouteAuthFilterSpec) DeepCopy() *RouteAuthFilterSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteJWTClaimVerification) DeepCopyInto(out *RouteJWTClaimVerification) { - *out = *in - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteJWTClaimVerification. -func (in *RouteJWTClaimVerification) DeepCopy() *RouteJWTClaimVerification { - if in == nil { - return nil - } - out := new(RouteJWTClaimVerification) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteJWTProvider) DeepCopyInto(out *RouteJWTProvider) { - *out = *in - if in.VerifyClaims != nil { - in, out := &in.VerifyClaims, &out.VerifyClaims - *out = make([]RouteJWTClaimVerification, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteJWTProvider. -func (in *RouteJWTProvider) DeepCopy() *RouteJWTProvider { - if in == nil { - return nil - } - out := new(RouteJWTProvider) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteJWTRequirement) DeepCopyInto(out *RouteJWTRequirement) { - *out = *in - if in.Providers != nil { - in, out := &in.Providers, &out.Providers - *out = make([]RouteJWTProvider, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteJWTRequirement. -func (in *RouteJWTRequirement) DeepCopy() *RouteJWTRequirement { - if in == nil { - return nil - } - out := new(RouteJWTRequirement) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteRetryFilter) DeepCopyInto(out *RouteRetryFilter) { *out = *in diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_routeauthfilters.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_routeauthfilters.yaml index 373fbcedee..263d17ce29 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_routeauthfilters.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_routeauthfilters.yaml @@ -6,7 +6,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: routeauthfilters.consul.hashicorp.com spec: @@ -52,26 +52,40 @@ spec: description: RouteAuthFilterSpec defines the desired state of RouteAuthFilter. properties: jwt: - description: RouteJWTRequirement defines the JWT requirements per - provider. + description: This re-uses the JWT requirement type from Gateway Policy + Types. properties: providers: + description: Providers is a list of providers to consider when + verifying a JWT. items: - description: RouteJWTProvider defines the configuration for - a specific JWT provider. + description: GatewayJWTProvider holds the provider and claim + verification information. properties: name: + description: Name is the name of the JWT provider. There + MUST be a corresponding "jwt-provider" config entry with + this name. type: string verifyClaims: + description: VerifyClaims is a list of additional claims + to verify in a JWT's payload. items: - description: RouteJWTClaimVerification defines the specific - claims to be verified. + description: GatewayJWTClaimVerification holds the actual + claim information to be verified. properties: path: + description: Path is the path to the claim in the + token JSON. items: type: string type: array value: + description: "Value is the expected value at the given + path: - If the type at the path is a list then we + verify that this value is contained in the list. + \n - If the type at the path is a string then we + verify that this value matches." type: string required: - path @@ -80,7 +94,6 @@ spec: type: array required: - name - - verifyClaims type: object type: array required: @@ -130,3 +143,9 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/control-plane/go.mod b/control-plane/go.mod index c199f954d6..3cf9138266 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230511143918-bd16ab83383d github.com/hashicorp/consul-server-connection-manager v0.1.3 - github.com/hashicorp/consul/api v1.10.1-0.20230821180813-217d305b38d5 + github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924 github.com/hashicorp/consul/sdk v0.14.1 github.com/hashicorp/go-bexpr v0.1.11 github.com/hashicorp/go-discover v0.0.0-20230519164032-214571b6a530 @@ -28,8 +28,8 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.3 go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 - golang.org/x/text v0.11.0 + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 + golang.org/x/text v0.12.0 golang.org/x/time v0.3.0 gomodules.xyz/jsonpatch/v2 v2.3.0 gopkg.in/yaml.v2 v2.4.0 @@ -70,7 +70,7 @@ require ( github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect github.com/go-logr/zapr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -97,7 +97,7 @@ require ( github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/mdns v1.0.4 // indirect github.com/hashicorp/vault/sdk v0.7.0 // indirect @@ -111,7 +111,7 @@ require ( github.com/linode/linodego v0.7.1 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect @@ -143,14 +143,14 @@ require ( go.opencensus.io v0.22.4 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.13.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sync v0.2.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/term v0.10.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/term v0.11.0 // indirect + golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect google.golang.org/api v0.30.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index 36797f0e3d..973cb5552a 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -142,8 +142,8 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= @@ -264,18 +264,10 @@ github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230511143918-bd16ab83 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230511143918-bd16ab83383d/go.mod h1:IHIHMzkoMwlv6rLsgwcoFBVYupR7/1pKEOHBMjD4L0k= github.com/hashicorp/consul-server-connection-manager v0.1.3 h1:fxsZ15XBNNWhV26yBVdCcnxHwSRgf9wqHGS2ZVCQIhc= github.com/hashicorp/consul-server-connection-manager v0.1.3/go.mod h1:Md2IGKaFJ4ek9GUA0pW1S2R60wpquMOUs27GiD9kZd0= -github.com/hashicorp/consul/api v1.10.1-0.20230802160219-cf2bf7fdecdf h1:XCfEJhwSx188jLPjctsGoOfG7OueuXaqceR0HwHAH1s= -github.com/hashicorp/consul/api v1.10.1-0.20230802160219-cf2bf7fdecdf/go.mod h1:TqtEfVYyzax2gaBwU1vsCGFcysmK9g9UANUWCd8qMBw= -github.com/hashicorp/consul/api v1.10.1-0.20230821140749-587663dbcbd1 h1:HulZABqJoIf1NLkWkXRqH1Vl/OLKiJQBEuuFk/XezuI= -github.com/hashicorp/consul/api v1.10.1-0.20230821140749-587663dbcbd1/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= -github.com/hashicorp/consul/api v1.10.1-0.20230821180813-217d305b38d5 h1:TTTgXv9YeaRnODyFP1k2b2Nq5RIGrUUgI5SkDhuSNwM= -github.com/hashicorp/consul/api v1.10.1-0.20230821180813-217d305b38d5/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= -github.com/hashicorp/consul/api v1.24.0 h1:u2XyStA2j0jnCiVUU7Qyrt8idjRn4ORhK6DlvZ3bWhA= -github.com/hashicorp/consul/api v1.24.0/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= +github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924 h1:NPhzdwDho2r8pQv31oeGLlco7fnJ1i0WLYjtSXqWEck= +github.com/hashicorp/consul/api v1.10.1-0.20230825164720-ecdcde430924/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= github.com/hashicorp/consul/proto-public v0.1.0 h1:O0LSmCqydZi363hsqc6n2v5sMz3usQMXZF6ziK3SzXU= github.com/hashicorp/consul/proto-public v0.1.0/go.mod h1:vs2KkuWwtjkIgA5ezp4YKPzQp4GitV+q/+PvksrA92k= -github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU= -github.com/hashicorp/consul/sdk v0.14.0/go.mod h1:gHYeuDa0+0qRAD6Wwr6yznMBvBwHKoxSBoW5l73+saE= github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -329,8 +321,8 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 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= @@ -405,8 +397,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -582,8 +574,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -594,8 +586,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= -golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -618,8 +610,8 @@ 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -663,8 +655,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= 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= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -685,8 +677,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 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= @@ -751,13 +743,14 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -767,8 +760,8 @@ 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= @@ -821,8 +814,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= 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=