├── .gitignore ├── Makefile ├── README.md ├── cmd ├── cmd.go ├── socksclient │ └── socksclient.go ├── tcpproxy │ └── tcpproxy.go ├── tlssocks │ ├── authentication.go │ ├── authentication_test.go │ └── tlssocks.go └── tlssocksproxy │ └── tlssocksproxy.go ├── docker ├── local-test │ ├── docker-compose.yml │ └── tlssocks │ │ ├── destinations.yaml │ │ └── users.htpasswd ├── tcpproxy │ ├── Dockerfile │ └── Dockerfile.hub ├── tlssocks │ ├── Dockerfile │ └── Dockerfile.hub └── tlssocksproxy │ ├── Dockerfile │ └── Dockerfile.hub ├── go.mod └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.git* 3 | # Binaries for programs and plugins 4 | *.exe 5 | *.exe~ 6 | *.dll 7 | *.so 8 | *.dylib 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # generated certs 17 | /docker/local-test/tlssocks/certificate.* 18 | 19 | # golang 20 | /vendor -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | DOMAIN="*.example.com" 4 | SAN=DNS:$(DOMAIN),DNS:localhost,DNS:127.0.0.1 5 | 6 | cert-create: 7 | rm -rf docker/local-test/tlssocks/certificate.* 8 | openssl req -newkey rsa:2048 -nodes -keyout docker/local-test/tlssocks/certificate.key -subj "/C=DE/ST=Bavaria/L=Munich/O=foomo/CN=$(DOMAIN)" -out docker/local-test/tlssocks/certificate.csr 9 | openssl x509 -req -extfile <(printf "subjectAltName=DNS:$(DOMAIN),DNS:localhost,DNS:127.0.0.1") -days 365 -signkey docker/local-test/tlssocks/certificate.key -in docker/local-test/tlssocks/certificate.csr -out docker/local-test/tlssocks/certificate.crt 10 | 11 | cert-show: 12 | openssl x509 -in docker/local-test/tlssocks/certificate.crt -text -noout 13 | 14 | cert-trust-on-mac: 15 | sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain docker/local-test/tlssocks/certificate.crt 16 | 17 | docker-local-test: cert-create cert-show 18 | cd docker/local-test && docker-compose up -d 19 | 20 | docker-build: 21 | foomo -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socks5 over multiple network zones tunneled through a tls tcp connection 2 | 3 | ```ascii 4 | +-------------------+ +--------------+ +--------------+ +-----------------+ 5 | | source zone | | zone A | | zone ... | | target zone | 6 | | +---------------+ | | | | | | +-------------+ | 7 | | | | | | | | | | | | | 8 | | | client A | | | | | | | | service A | | 9 | | | | | | | | | | | | | 10 | | +-------+-------+ | | | | | | +------^------+ | 11 | | | | | | | | | | | 12 | | +-------v-------+ | | +----------+ | | +----------+ | | +------+------+ | 13 | | | | | | | | | | | | | | | | | 14 | | | tlssocksproxy +-------> tcpproxy +-------> tcpproxy +-------> tlssocks | | 15 | | | | | | | | | | | | | | | | | 16 | | +-------^-------+ | | +----------+ | | +----------+ | | +------+------+ | 17 | | | | | | | | | | | 18 | | +-------+-------+ | | | | | | +------v------+ | 19 | | | | | | | | | | | | | 20 | | | client ... | | | | | | | | service ... | | 21 | | | | | | | | | | | | | 22 | | +---------------+ | | | | | | +-------------+ | 23 | | | +--------------+ +--------------+ | | 24 | | | | | 25 | | +-----------------------------------------> | 26 | | | tls connection over n zones | | 27 | +-------------------+ +-----------------+ 28 | ``` 29 | ## example project 30 | 31 | Example docker-compose project in docker/localtest - should help to understand the configuration 32 | 33 | ```bash 34 | # run example project 35 | make docker-local-test 36 | ``` 37 | 38 | ```bash 39 | # try it 40 | 41 | # works for jan 42 | curl -vvv --proxy socks5h://jan:secret@127.0.0.1:8000 http://echo:8080/ 43 | * Trying 127.0.0.1... 44 | * TCP_NODELAY set 45 | * SOCKS5 communication to echo:8080 46 | * SOCKS5 request granted. 47 | * Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0) 48 | > GET / HTTP/1.1 49 | > Host: echo:8080 50 | > User-Agent: curl/7.54.0 51 | > Accept: */* 52 | > 53 | < HTTP/1.1 200 OK 54 | < X-App-Name: http-echo 55 | < X-App-Version: 0.2.3 56 | < Date: Mon, 06 Aug 2018 09:44:03 GMT 57 | < Content-Length: 12 58 | < Content-Type: text/plain; charset=utf-8 59 | < 60 | hello-world 61 | * Connection #0 to host 127.0.0.1 left intact 62 | 63 | # does not work for peter 64 | curl -vvv --proxy socks5h://peter:secret@127.0.0.1:8000 http://echo:8080/ 65 | * Trying 127.0.0.1... 66 | * TCP_NODELAY set 67 | * SOCKS5 communication to echo:8080 68 | * Can't complete SOCKS5 connection to 0.0.0.0:0. (2) 69 | * Closing connection 0 70 | curl: (7) Can't complete SOCKS5 connection to 0.0.0.0:0. (2) 71 | 72 | ``` 73 | 74 | ## tlssocksproxy 75 | 76 | Opens an tls encrypted connection to tlssocks - optionally through one or multiple tcpproxies and makes it available as a "normal" socks5 server. 77 | 78 | ```bash 79 | # running a tlssocksproxy locally to connect a remote tlssocks using tls encryption 80 | docker run --rm -p="8000:8000" foomo/tlssocksproxy:latest -addr="0.0.0.0:8000" -server="tlssocks.example.com:8765" 81 | ``` 82 | 83 | ## tcpproxy 84 | 85 | Very light weight wrapper around googles [https://github.com/google/tcpproxy](https://github.com/google/tcpproxy) - can be daisychained. 86 | 87 | ## tlssocks 88 | 89 | Based on [github.com/armon/go-socks5](github.com/armon/go-socks5) wrapped by [https://golang.org/pkg/crypto/tls/](https://golang.org/pkg/crypto/tls/). 90 | 91 | - tls protection 92 | - authentication with bcrypt hashed passwords (htpasswd compatible) 93 | - destinations configuration 94 | 95 | Managing credentials: 96 | 97 | Can be done with good old htpasswd - in case of doubt `man htpasswd` 98 | 99 | ```bash 100 | # set the password for a user in an existing file using bcrypt 101 | htpasswd -B path/to/users.htpasswd 102 | ``` 103 | 104 | Configuring destinations: 105 | 106 | By default every proxy request is denied, except it is explicitly allowed through the destinations configuration. 107 | 108 | Destinations are configured on a name basis and allowed for ports and users. 109 | 110 | WARNING - if you are running multiple vhosts on one destination all of them are accessible, since tlssocks is not inspecting the incoming traffic. 111 | 112 | ```yaml 113 | --- 114 | # destination www.heise.de will be accessible trough ports 80, 443 for users jan and peter 115 | www.heise.de: 116 | ports: 117 | - 80 118 | - 443 119 | users: 120 | - jan 121 | - peter 122 | # destination echo is acce 123 | echo: 124 | ports: 125 | - 8080 126 | users: 127 | - jan 128 | 129 | www.google.com: 130 | ports: 131 | - 443 132 | users: 133 | - peter 134 | ... 135 | ``` 136 | 137 | ## caveats / todos 138 | 139 | - only name based destinations are supported 140 | 141 | ## security concerns 142 | 143 | All vhosts on a destination can be accessed through the allowed ports - there is no traffic inspection to prevent this. 144 | -------------------------------------------------------------------------------- /cmd/cmd.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | "os" 10 | "os/signal" 11 | "syscall" 12 | "time" 13 | 14 | "github.com/prometheus/client_golang/prometheus" 15 | "github.com/prometheus/client_golang/prometheus/promauto" 16 | "github.com/prometheus/client_golang/prometheus/promhttp" 17 | "go.uber.org/zap" 18 | ) 19 | 20 | func TryFatal(log *zap.Logger, err error, msg string, fields ...zap.Field) { 21 | if err != nil { 22 | log.Fatal(msg, append(fields, zap.Error(err))...) 23 | } 24 | } 25 | 26 | func RecoverAndLogPanic(log *zap.Logger) { 27 | if r := recover(); r != nil { 28 | var err error 29 | switch x := r.(type) { 30 | case string: 31 | err = errors.New(x) 32 | case error: 33 | err = x 34 | default: 35 | err = fmt.Errorf("unknown panic of type: %T", r) 36 | } 37 | log.Error("Panic occurred in serve thread", zap.Error(err)) 38 | } 39 | } 40 | 41 | func RunPrometheusHandler(ctx context.Context, log *zap.Logger, address string) { 42 | h := http.NewServeMux() 43 | h.Handle("/metrics", promhttp.Handler()) 44 | server := &http.Server{Addr: address, Handler: h} 45 | 46 | go func() { 47 | if err := server.ListenAndServe(); err != nil { 48 | log.Fatal("Failed to start prometheus handler", zap.Error(err)) 49 | } 50 | }() 51 | 52 | select { 53 | case <-ctx.Done(): 54 | log.Info("Shutdown prometheus handler in progress") 55 | if err := server.Shutdown(ctx); err != nil && err != context.Canceled { 56 | log.Fatal("Failed to Shutdown prometheus handler", zap.Error(err)) 57 | } 58 | } 59 | } 60 | 61 | func SilentClose(c io.Closer) { 62 | if c != nil { 63 | _ = c.Close() 64 | } 65 | } 66 | 67 | func CtxCancelOnOsSignal(log *zap.Logger) context.Context { 68 | ctx, cancel := context.WithCancel(context.Background()) 69 | c := make(chan os.Signal, 1) 70 | signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGABRT) 71 | 72 | go func() { 73 | defer func() { 74 | signal.Stop(c) 75 | cancel() 76 | }() 77 | select { 78 | case c2 := <-c: 79 | log.Info("Received interrupt signal and cancelling context", zap.String("signal", c2.String())) 80 | cancel() 81 | case <-ctx.Done(): 82 | } 83 | }() 84 | return ctx 85 | } 86 | 87 | func NewSummaryVector(name string, description string, labels []string) *prometheus.SummaryVec { 88 | return promauto.NewSummaryVec(prometheus.SummaryOpts{ 89 | Namespace: "mzg", 90 | Subsystem: "mitsproxy", 91 | Name: name, 92 | Help: description, 93 | Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, 94 | MaxAge: 1 * time.Hour, 95 | BufCap: 3 * prometheus.DefBufCap, 96 | }, labels) 97 | } 98 | -------------------------------------------------------------------------------- /cmd/socksclient/socksclient.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "net/http/httputil" 9 | "net/url" 10 | "os" 11 | "time" 12 | 13 | "github.com/foomo/tlssocks/cmd" 14 | "go.uber.org/zap" 15 | ) 16 | 17 | func main() { 18 | log, _ := zap.NewProduction() 19 | defer log.Sync() 20 | flagSocksServer := flag.String("socks-server", "socks5://test:test@127.0.0.1:8000", "addr of socks server like socks://user:pass@127.0.0.1:8000") 21 | flag.Parse() 22 | 23 | if len(flag.Args()) != 1 { 24 | log.Fatal("usage: " + os.Args[0] + " -socks-server=127.0.0.1:8000 http://www.google.com/") 25 | } 26 | 27 | urlToFetch := flag.Arg(0) 28 | 29 | proxyURL, err := url.Parse(*flagSocksServer) 30 | cmd.TryFatal(log, err, "invalid proxy server URL") 31 | 32 | response, err := newClient(proxyURL).Get(urlToFetch) 33 | cmd.TryFatal(log, err, "could not GET", zap.String("url", urlToFetch)) 34 | defer cmd.SilentClose(response.Body) 35 | 36 | respBytes, err := httputil.DumpResponse(response, true) 37 | cmd.TryFatal(log, err, "failed httputil.DumpResponse") 38 | 39 | fmt.Println(string(respBytes)) 40 | } 41 | 42 | func newClient(proxyURL *url.URL) *http.Client { 43 | transport := &http.Transport{ 44 | Proxy: http.ProxyURL(proxyURL), 45 | DialContext: (&net.Dialer{ 46 | Timeout: 30 * time.Second, 47 | KeepAlive: 30 * time.Second, 48 | DualStack: true, 49 | }).DialContext, 50 | MaxIdleConns: 100, 51 | IdleConnTimeout: 90 * time.Second, 52 | TLSHandshakeTimeout: 10 * time.Second, 53 | ExpectContinueTimeout: 1 * time.Second, 54 | } 55 | return &http.Client{ 56 | Transport: transport, 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cmd/tcpproxy/tcpproxy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/google/tcpproxy" 7 | "go.uber.org/zap" 8 | ) 9 | 10 | func main() { 11 | logger, _ := zap.NewProduction() 12 | defer logger.Sync() 13 | 14 | flagDestination := flag.String("destination", "", "address of destination server like 127.0.0.1:8000") 15 | flagAddr := flag.String("addr", "", "where to listen like 127.0.0.1:8001") 16 | 17 | flag.Parse() 18 | if *flagDestination == "" { 19 | flag.Usage() 20 | logger.Fatal("empty socks server") 21 | } 22 | if *flagAddr == "" { 23 | flag.Usage() 24 | logger.Fatal("empty addr - I do not know where to listen") 25 | } 26 | 27 | logger.Info( 28 | "starting tcp proxy", 29 | zap.String("addr", *flagAddr), 30 | zap.String("destination", *flagDestination), 31 | ) 32 | var p tcpproxy.Proxy 33 | p.AddRoute(*flagAddr, tcpproxy.To(*flagDestination)) 34 | logger.Fatal("shutting down", zap.Error(p.Run())) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/tlssocks/authentication.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "time" 7 | 8 | "github.com/armon/go-socks5" 9 | "github.com/patrickmn/go-cache" 10 | "github.com/spaolacci/murmur3" 11 | "go.uber.org/zap" 12 | "golang.org/x/crypto/bcrypt" 13 | ) 14 | 15 | const defaultBasicAuthTTL = 90 * time.Second 16 | 17 | var basicAuthCache = cache.New(120*time.Second, 60*time.Minute) 18 | 19 | type Credentials struct { 20 | disableCaching bool 21 | htpasswd map[string]string 22 | } 23 | 24 | func (s Credentials) Valid(user, password string) bool { 25 | hashedPW := s.htpasswd[user] 26 | hashedPWb := []byte(hashedPW) 27 | plainPWb := []byte(password) 28 | 29 | if s.disableCaching { 30 | return nil == bcrypt.CompareHashAndPassword(hashedPWb, plainPWb) 31 | } 32 | 33 | hasher := murmur3.New64() 34 | 35 | cachedPass, inCache := basicAuthCache.Get(hashedPW) 36 | if !inCache { 37 | ok := nil == bcrypt.CompareHashAndPassword(hashedPWb, plainPWb) 38 | if !ok { 39 | return false 40 | } 41 | 42 | hasher.Write(plainPWb) 43 | basicAuthCache.Set(hashedPW, string(hasher.Sum(nil)), defaultBasicAuthTTL) 44 | return true 45 | } 46 | 47 | hasher.Write(plainPWb) 48 | if cachedPass.(string) != string(hasher.Sum(nil)) { 49 | return nil == bcrypt.CompareHashAndPassword(hashedPWb, plainPWb) 50 | } 51 | 52 | return true 53 | } 54 | 55 | type authenticator struct { 56 | log *zap.Logger 57 | Destinations map[string]*Destination 58 | resolvedNames map[string][]string 59 | } 60 | 61 | func newAuthenticator(log *zap.Logger, destinations map[string]*Destination) (*authenticator, error) { 62 | sa := &authenticator{ 63 | log: log, 64 | Destinations: destinations, 65 | } 66 | names := make([]string, 0, len(destinations)) 67 | for name := range destinations { 68 | names = append(names, name) 69 | } 70 | 71 | resolvedNames, err := resolveNames(names) 72 | if err != nil { 73 | return nil, err 74 | } 75 | sa.resolvedNames = resolvedNames 76 | 77 | go func() { 78 | time.Sleep(time.Second * 10) 79 | 80 | resolvedNames, err := resolveNames(names) 81 | if err == nil { 82 | sa.resolvedNames = resolvedNames 83 | } else { 84 | log.Warn("could not resolve names", zap.Error(err)) 85 | } 86 | }() 87 | return sa, nil 88 | } 89 | 90 | func resolveNames(names []string) (map[string][]string, error) { 91 | newResolvedNames := map[string][]string{} 92 | for _, name := range names { 93 | addrs, err := net.LookupHost(name) 94 | if err != nil { 95 | return nil, err 96 | } 97 | newResolvedNames[name] = addrs 98 | } 99 | return newResolvedNames, nil 100 | } 101 | 102 | func (sa *authenticator) Allow(ctx context.Context, req *socks5.Request) (newCtx context.Context, allowed bool) { 103 | allowed = false 104 | newCtx = ctx 105 | zapTo := zap.String("to", req.DestAddr.String()) 106 | zapUser := zap.String("for", req.AuthContext.Payload["Username"]) 107 | 108 | for name, ips := range sa.resolvedNames { 109 | zapName := zap.String("name", name) 110 | for _, ip := range ips { 111 | if ip == req.DestAddr.IP.String() { 112 | destination, destinationOK := sa.Destinations[name] 113 | if destinationOK { 114 | for _, allowedPort := range destination.Ports { 115 | if allowedPort == req.DestAddr.Port { 116 | if len(destination.Users) == 0 { 117 | allowed = true 118 | } 119 | if !allowed { 120 | userNameInContext, userNameInContextOK := req.AuthContext.Payload["Username"] 121 | if !userNameInContextOK { 122 | // explicit user expected, but not found 123 | sa.log.Info("denied - no user found", zapName, zapTo) 124 | return 125 | } 126 | for _, userName := range destination.Users { 127 | if userName == userNameInContext { 128 | allowed = true 129 | break 130 | } 131 | } 132 | if !allowed { 133 | sa.log.Info("denied", zapName, zapTo, zapUser) 134 | return 135 | } 136 | } 137 | if allowed { 138 | sa.log.Info("allowed", zapName, zapTo, zapUser) 139 | 140 | allowed = true 141 | return 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | } 149 | sa.log.Info("denied", zapTo, zapUser) 150 | return 151 | } 152 | -------------------------------------------------------------------------------- /cmd/tlssocks/authentication_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestCredentials_Valid(t *testing.T) { 6 | testUser := map[string]string{"test":"$2y$10$n0MZPvD3lqFlEGqbZzu7vuAvdIYn1qJJAriFmSpXq/HbOQZ1nup3a"} 7 | 8 | type fields struct { 9 | disableCaching bool 10 | htpasswd map[string]string 11 | } 12 | type args struct { 13 | user string 14 | password string 15 | } 16 | tests := []struct { 17 | name string 18 | fields fields 19 | args args 20 | want bool 21 | }{ 22 | {name: "no htpasswd but user pw", fields: fields{ 23 | disableCaching: false, 24 | htpasswd: nil, 25 | }, args: args{ 26 | user: "test", 27 | password: "test", 28 | },want: false}, 29 | 30 | {name: "no htpasswd no user pw nc", fields: fields{ 31 | disableCaching: false, 32 | htpasswd: nil, 33 | }, args: args{ 34 | user: "", 35 | password: "", 36 | },want: false}, 37 | 38 | {name: "no htpasswd no user pw c", fields: fields{ 39 | disableCaching: true, 40 | htpasswd: nil, 41 | }, args: args{ 42 | user: "", 43 | password: "", 44 | },want: false}, 45 | 46 | {name: "htpasswd no user pw", fields: fields{ 47 | disableCaching: false, 48 | htpasswd: testUser, 49 | }, args: args{ 50 | user: "", 51 | password: "", 52 | },want: false}, 53 | 54 | {name: "htpasswd user wrong pw", fields: fields{ 55 | disableCaching: false, 56 | htpasswd: testUser, 57 | }, args: args{ 58 | user: "test", 59 | password: "test ", 60 | },want: false}, 61 | 62 | {name: "htpasswd user correct pw uncached", fields: fields{ 63 | disableCaching: false, 64 | htpasswd: testUser, 65 | }, args: args{ 66 | user: "test", 67 | password: "test", 68 | },want: true}, 69 | 70 | {name: "htpasswd user correct pw cached", fields: fields{ 71 | disableCaching: false, 72 | htpasswd: testUser, 73 | }, args: args{ 74 | user: "test", 75 | password: "test", 76 | },want: true}, 77 | 78 | {name: "htpasswd user correct pw cached but wrong pw", fields: fields{ 79 | disableCaching: false, 80 | htpasswd: testUser, 81 | }, args: args{ 82 | user: "test", 83 | password: "test1", 84 | },want: false}, 85 | 86 | } 87 | for _, tt := range tests { 88 | t.Run(tt.name, func(t *testing.T) { 89 | s := Credentials{ 90 | disableCaching: tt.fields.disableCaching, 91 | htpasswd: tt.fields.htpasswd, 92 | } 93 | if got := s.Valid(tt.args.user, tt.args.password); got != tt.want { 94 | t.Errorf("Valid() = %v, want %v", got, tt.want) 95 | } 96 | }) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /cmd/tlssocks/tlssocks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "flag" 6 | "io/ioutil" 7 | 8 | "github.com/armon/go-socks5" 9 | "github.com/foomo/htpasswd" 10 | "github.com/foomo/tlssocks/cmd" 11 | "go.uber.org/zap" 12 | "gopkg.in/yaml.v2" 13 | ) 14 | 15 | type Destination struct { 16 | Users []string 17 | Ports []int 18 | } 19 | 20 | func main() { 21 | log, _ := zap.NewProduction() 22 | defer log.Sync() 23 | 24 | flagAddr := flag.String("addr", "", "where to listen like 127.0.0.1:8000") 25 | flagHtpasswdFile := flag.String("auth", "", "basic auth file") 26 | flagDestinationsFile := flag.String("destinations", "", "file with destinations config") 27 | flagCert := flag.String("cert", "", "path to server cert.pem") 28 | flagKey := flag.String("key", "", "path to server key.pem") 29 | flagDisableBasicAuthCaching := flag.Bool("disable-basic-auth-caching", false, "if set disables caching of basic auth user and password") 30 | flag.Parse() 31 | 32 | destinationBytes, err := ioutil.ReadFile(*flagDestinationsFile) 33 | cmd.TryFatal(log, err, "can not read destinations config") 34 | 35 | destinations := map[string]*Destination{} 36 | 37 | cmd.TryFatal(log, yaml.Unmarshal(destinationBytes, destinations), "can not parse destinations") 38 | 39 | passwordHashes, err := htpasswd.ParseHtpasswdFile(*flagHtpasswdFile) 40 | cmd.TryFatal(log, err, "basic auth file sucks") 41 | credentials := Credentials{disableCaching: *flagDisableBasicAuthCaching, htpasswd: passwordHashes} 42 | 43 | suxx5, err := newAuthenticator(log, destinations) 44 | cmd.TryFatal(log, err, "newAuthenticator failed") 45 | 46 | autenticator := socks5.UserPassAuthenticator{Credentials: credentials} 47 | 48 | conf := &socks5.Config{ 49 | Rules: suxx5, 50 | AuthMethods: []socks5.Authenticator{autenticator}, 51 | } 52 | server, err := socks5.New(conf) 53 | cmd.TryFatal(log, err, "socks5.New failed") 54 | 55 | log.Info( 56 | "starting tls server", 57 | zap.String("addr", *flagAddr), 58 | zap.String("cert", *flagCert), 59 | zap.String("key", *flagKey), 60 | ) 61 | 62 | cert, err := tls.LoadX509KeyPair(*flagCert, *flagKey) 63 | cmd.TryFatal(log, err, "could not load server key pair") 64 | 65 | listener, err := tls.Listen("tcp", *flagAddr, &tls.Config{Certificates: []tls.Certificate{cert}}) 66 | cmd.TryFatal(log, err, "could not listen for tcp / tls", zap.String("addr", *flagAddr)) 67 | 68 | cmd.TryFatal(log, server.Serve(listener), "server failed") 69 | } 70 | -------------------------------------------------------------------------------- /cmd/tlssocksproxy/tlssocksproxy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "flag" 7 | "io" 8 | "net" 9 | "sync/atomic" 10 | "time" 11 | 12 | "github.com/foomo/tlssocks/cmd" 13 | "go.uber.org/zap" 14 | ) 15 | 16 | const ( 17 | defaultTimeout = 180 * time.Second 18 | defaultPrometheusAddress = ":9200" 19 | connDeadline = 60 * time.Second 20 | ) 21 | 22 | var proxyServeSummary = cmd.NewSummaryVector( 23 | "serve_duration_seconds", 24 | "Measures serve duration for mitsproxy in seconds", 25 | nil, 26 | ) 27 | 28 | func main() { 29 | log, _ := zap.NewProduction() 30 | defer log.Sync() 31 | 32 | flagInsecureSkipVerify := flag.Bool("insecure-skip-verify", false, "allow insecure skipping of peer verification, when talking to the server") 33 | flagLocalAddr := flag.String("addr", "0.0.0.0:8080", "address to listen to like 0.0.0.0:8001") 34 | flagRemoteAddr := flag.String("server", "", "address of the tls socks server like 0.0.0.0:8000") 35 | flag.Parse() 36 | 37 | log.Info( 38 | "Starting socks proxy to listen on addr and forward requests to server", 39 | zap.String("local_addr", *flagLocalAddr), 40 | zap.String("remote_addr", *flagRemoteAddr), 41 | ) 42 | 43 | localListener, err := net.Listen("tcp", *flagLocalAddr) 44 | if err != nil { 45 | log.Fatal("Error listening for incoming socks connections", zap.Error(err)) 46 | } 47 | 48 | defer cmd.SilentClose(localListener) 49 | 50 | tlsConfig := &tls.Config{ 51 | InsecureSkipVerify: *flagInsecureSkipVerify, 52 | } 53 | if tlsConfig.InsecureSkipVerify { 54 | log.Warn("Running without verification of the tls server - this is dangerous") 55 | } 56 | ctx := cmd.CtxCancelOnOsSignal(log) 57 | 58 | go cmd.RunPrometheusHandler(ctx, log, defaultPrometheusAddress) 59 | 60 | var connID uint64 61 | for { 62 | localConn, err := localListener.Accept() 63 | if err != nil { 64 | log.Fatal("error accepting incoming connections", zap.Error(err)) 65 | } 66 | connID++ 67 | go serve(ctx, log, localConn, *flagRemoteAddr, tlsConfig, connID) 68 | } 69 | } 70 | 71 | func serve(ctx context.Context, logger *zap.Logger, localConn net.Conn, remoteAddress string, tlsConfig *tls.Config, connID uint64) { 72 | start := time.Now() 73 | 74 | // Recover if a panic occurs 75 | defer cmd.RecoverAndLogPanic(logger) 76 | defer cmd.SilentClose(localConn) 77 | 78 | remoteConn, err := tls.DialWithDialer(&net.Dialer{ 79 | Timeout: defaultTimeout, 80 | }, "tcp", remoteAddress, tlsConfig) 81 | if err != nil { 82 | logger.Warn("could not reach remote tls server", zap.Error(err)) 83 | return 84 | } 85 | defer cmd.SilentClose(remoteConn) 86 | 87 | p := &proxy{ 88 | log: logger, 89 | wait: make(chan struct{}), 90 | } 91 | 92 | deadline := start.Add(connDeadline) 93 | _ = localConn.SetDeadline(deadline) 94 | _ = remoteConn.SetDeadline(deadline) 95 | 96 | go p.pipe(ctx, remoteConn, localConn, isLocalConnection) 97 | go p.pipe(ctx, localConn, remoteConn, isLocalNotConnection) 98 | 99 | <-p.wait 100 | logger.Info( 101 | "request served", 102 | zap.Duration("duration", time.Since(start)), 103 | zap.Uint64("bytes_sent", atomic.LoadUint64(&p.sentBytes)), 104 | zap.Uint64("bytes_received", atomic.LoadUint64(&p.receivedBytes)), 105 | zap.Uint64("conn_id", connID), 106 | zap.String("from", localConn.RemoteAddr().String()), 107 | ) 108 | 109 | proxyServeSummary.WithLabelValues().Observe(time.Since(start).Seconds()) 110 | } 111 | 112 | type proxy struct { 113 | log *zap.Logger 114 | sentBytes uint64 115 | receivedBytes uint64 116 | wait chan struct{} 117 | erred uint32 118 | } 119 | 120 | const ( 121 | isLocalConnection = true 122 | isLocalNotConnection = false 123 | ) 124 | 125 | func (p *proxy) pipe(ctx context.Context, dst io.Writer, src io.Reader, isLocal bool) { 126 | buff := make([]byte, 65535) 127 | for { 128 | if ctx.Err() != nil { 129 | p.err("context error", ctx.Err()) 130 | return 131 | } 132 | 133 | n, err := src.Read(buff[:]) 134 | if err != nil { 135 | p.err("Read failed", err) 136 | return 137 | } 138 | 139 | n, err = dst.Write(buff[:n]) 140 | if err != nil { 141 | p.err("Write failed", err) 142 | return 143 | } 144 | if isLocal { 145 | atomic.AddUint64(&p.sentBytes, uint64(n)) 146 | } else { 147 | atomic.AddUint64(&p.receivedBytes, uint64(n)) 148 | } 149 | } 150 | } 151 | 152 | func (p *proxy) err(message string, err error) { 153 | if atomic.LoadUint32(&p.erred) == 1 { 154 | return 155 | } 156 | if err != io.EOF { 157 | p.log.Warn(message, zap.Error(err)) 158 | } 159 | 160 | atomic.StoreUint32(&p.erred, 1) 161 | 162 | select { 163 | case <-p.wait: 164 | // channel has already been closed 165 | default: 166 | close(p.wait) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /docker/local-test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2.6" 2 | 3 | services: 4 | 5 | socksproxy: 6 | build: 7 | context: ../.. 8 | dockerfile: docker/tlssocksproxy/Dockerfile 9 | restart: unless-stopped 10 | command: 11 | - "-addr=0.0.0.0:8000" 12 | - "-server=tunneltunnel:8000" 13 | - "-insecure-skip-verify" 14 | ports: 15 | - 8000:8000 16 | logging: 17 | driver: "json-file" 18 | options: 19 | max-size: "100m" 20 | max-file: "10" 21 | 22 | tunneltunnel: 23 | build: 24 | context: ../.. 25 | dockerfile: docker/tcpproxy/Dockerfile 26 | restart: unless-stopped 27 | command: 28 | - "-addr=0.0.0.0:8000" 29 | - "-destination=tunnel:8000" 30 | expose: 31 | - 8000 32 | networks: 33 | - default 34 | logging: 35 | driver: "json-file" 36 | options: 37 | max-size: "100m" 38 | max-file: "10" 39 | 40 | tunnel: 41 | build: 42 | context: ../.. 43 | dockerfile: docker/tcpproxy/Dockerfile 44 | restart: unless-stopped 45 | command: 46 | - "-addr=0.0.0.0:8000" 47 | - "-destination=tlssocks:8001" 48 | expose: 49 | - 8000 50 | logging: 51 | driver: "json-file" 52 | options: 53 | max-size: "100m" 54 | max-file: "10" 55 | 56 | tlssocks: 57 | build: 58 | context: ../.. 59 | dockerfile: docker/tlssocks/Dockerfile 60 | restart: unless-stopped 61 | command: 62 | - "-addr=0.0.0.0:8001" 63 | - "-auth=/tlssocks/users.htpasswd" 64 | - "-destinations=/tlssocks/destinations.yaml" 65 | - "-cert=/tlssocks/certificate.crt" 66 | - "-key=/tlssocks/certificate.key" 67 | expose: 68 | - 8001 69 | volumes: 70 | - ./tlssocks:/tlssocks 71 | logging: 72 | driver: "json-file" 73 | options: 74 | max-size: "100m" 75 | max-file: "10" 76 | -------------------------------------------------------------------------------- /docker/local-test/tlssocks/destinations.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | www.heise.de: 3 | ports: 4 | - 80 5 | - 443 6 | users: 7 | - jan 8 | - peter 9 | - test 10 | 11 | www.google.com: 12 | ports: 13 | - 443 14 | users: 15 | - peter 16 | - test 17 | -------------------------------------------------------------------------------- /docker/local-test/tlssocks/users.htpasswd: -------------------------------------------------------------------------------- 1 | jan:$2y$05$V2ka39tyqoRKbzcNnUYAQ.88shfljAWZXvKXjlnf6gBR15aswn25O 2 | peter:$2y$05$JdlFZOV1DNsvdU3KPkQCVu2355SXXkT/b77TrKSVzfE9nZG35S8Uy 3 | test:$2y$10$n0MZPvD3lqFlEGqbZzu7vuAvdIYn1qJJAriFmSpXq/HbOQZ1nup3a 4 | -------------------------------------------------------------------------------- /docker/tcpproxy/Dockerfile: -------------------------------------------------------------------------------- 1 | ############################## 2 | ###### STAGE: BUILD ###### 3 | ############################## 4 | FROM golang:alpine AS build-env 5 | 6 | WORKDIR /src 7 | 8 | COPY ./go.mod ./go.sum ./ 9 | 10 | # NOT SUPPORTED BY DOCKER HUB 11 | RUN --mount=type=cache,target=/root/.cache/go-build \ 12 | --mount=type=cache,target=/go/pkg/mod \ 13 | go mod download -x 14 | 15 | COPY ./ ./ 16 | 17 | # NOT SUPPORTED BY DOCKER HUB 18 | RUN --mount=type=cache,target=/root/.cache/go-build \ 19 | CGO_ENABLED=0 go build -trimpath -o /tcpproxy cmd/tcpproxy/tcpproxy.go 20 | 21 | ############################## 22 | ###### STAGE: CONTAINER ###### 23 | ############################## 24 | FROM alpine 25 | 26 | COPY --from=build-env /tcpproxy /usr/sbin/tcpproxy 27 | 28 | ENTRYPOINT [ "/usr/sbin/tcpproxy" ] 29 | 30 | CMD ["/usr/sbin/tlssocks"] 31 | -------------------------------------------------------------------------------- /docker/tcpproxy/Dockerfile.hub: -------------------------------------------------------------------------------- 1 | # Docker file for hub foomo/tcpproxy 2 | ############################## 3 | ###### STAGE: BUILD ###### 4 | ############################## 5 | FROM golang:alpine AS build-env 6 | 7 | WORKDIR /src 8 | 9 | COPY ./go.mod ./go.sum ./ 10 | 11 | RUN go mod download -x 12 | 13 | COPY ./ ./ 14 | 15 | RUN CGO_ENABLED=0 go build -trimpath -o /tcpproxy cmd/tcpproxy/tcpproxy.go 16 | 17 | ############################## 18 | ###### STAGE: CONTAINER ###### 19 | ############################## 20 | FROM alpine 21 | 22 | COPY --from=build-env /tcpproxy /usr/sbin/tcpproxy 23 | 24 | ENTRYPOINT [ "/usr/sbin/tcpproxy" ] 25 | 26 | CMD ["/usr/sbin/tlssocks"] 27 | -------------------------------------------------------------------------------- /docker/tlssocks/Dockerfile: -------------------------------------------------------------------------------- 1 | ############################## 2 | ###### STAGE: BUILD ###### 3 | ############################## 4 | FROM golang:alpine AS build-env 5 | 6 | WORKDIR /src 7 | 8 | COPY ./go.mod ./go.sum ./ 9 | 10 | # NOT SUPPORTED BY DOCKER HUB 11 | RUN --mount=type=cache,target=/root/.cache/go-build \ 12 | --mount=type=cache,target=/go/pkg/mod \ 13 | go mod download -x 14 | # RUN go mod download 15 | 16 | COPY ./ ./ 17 | 18 | # NOT SUPPORTED BY DOCKER HUB 19 | RUN --mount=type=cache,target=/root/.cache/go-build \ 20 | CGO_ENABLED=0 go build -trimpath -o /tlssocks cmd/tlssocks/tlssocks.go cmd/tlssocks/authentication.go 21 | 22 | ############################## 23 | ###### STAGE: CONTAINER ###### 24 | ############################## 25 | FROM alpine 26 | 27 | COPY --from=build-env /tlssocks /usr/sbin/tlssocks 28 | 29 | ENTRYPOINT [ "/usr/sbin/tlssocks" ] 30 | 31 | CMD ["/usr/sbin/tlssocks"] 32 | -------------------------------------------------------------------------------- /docker/tlssocks/Dockerfile.hub: -------------------------------------------------------------------------------- 1 | # Docker file for hub foomo/tlssocks 2 | ############################## 3 | ###### STAGE: BUILD ###### 4 | ############################## 5 | FROM golang:alpine AS build-env 6 | 7 | WORKDIR /src 8 | 9 | COPY ./go.mod ./go.sum ./ 10 | 11 | RUN go mod download -x 12 | 13 | COPY ./ ./ 14 | 15 | RUN CGO_ENABLED=0 go build -trimpath -o /tlssocks cmd/tlssocks/tlssocks.go cmd/tlssocks/authentication.go 16 | 17 | ############################## 18 | ###### STAGE: CONTAINER ###### 19 | ############################## 20 | FROM alpine 21 | 22 | COPY --from=build-env /tlssocks /usr/sbin/tlssocks 23 | 24 | ENTRYPOINT [ "/usr/sbin/tlssocks" ] 25 | 26 | CMD ["/usr/sbin/tlssocks"] 27 | -------------------------------------------------------------------------------- /docker/tlssocksproxy/Dockerfile: -------------------------------------------------------------------------------- 1 | ############################## 2 | ###### STAGE: BUILD ###### 3 | ############################## 4 | FROM golang:alpine AS build-env 5 | 6 | WORKDIR /src 7 | 8 | COPY ./go.mod ./go.sum ./ 9 | 10 | # NOT SUPPORTED BY DOCKER HUB 11 | RUN --mount=type=cache,target=/root/.cache/go-build \ 12 | --mount=type=cache,target=/go/pkg/mod \ 13 | go mod download -x 14 | # RUN go mod download 15 | 16 | COPY ./ ./ 17 | 18 | # CGO_ENABLED=1 go build -race ... 19 | # RUN apk add build-base 20 | 21 | # NOT SUPPORTED BY DOCKER HUB 22 | RUN --mount=type=cache,target=/root/.cache/go-build \ 23 | CGO_ENABLED=0 go build -trimpath -o /tlssocksproxy cmd/tlssocksproxy/tlssocksproxy.go 24 | 25 | # RUN CGO_ENABLED=0 go build -trimpath -o /tlssocksproxy cmd/tlssocksproxy/tlssocksproxy.go 26 | 27 | ############################## 28 | ###### STAGE: CONTAINER ###### 29 | ############################## 30 | FROM alpine 31 | 32 | COPY --from=build-env /tlssocksproxy /usr/sbin/tlssocksproxy 33 | 34 | ENTRYPOINT [ "/usr/sbin/tlssocksproxy" ] 35 | 36 | CMD ["/usr/sbin/tlssocksproxy"] 37 | -------------------------------------------------------------------------------- /docker/tlssocksproxy/Dockerfile.hub: -------------------------------------------------------------------------------- 1 | ############################## 2 | ###### STAGE: BUILD ###### 3 | ############################## 4 | FROM golang:alpine AS build-env 5 | 6 | WORKDIR /src 7 | 8 | COPY ./go.mod ./go.sum ./ 9 | 10 | RUN go mod download 11 | 12 | COPY ./ ./ 13 | 14 | # CGO_ENABLED=1 go build -race ... 15 | # RUN apk add build-base 16 | 17 | RUN CGO_ENABLED=0 go build -trimpath -o /tlssocksproxy cmd/tlssocksproxy/tlssocksproxy.go 18 | 19 | ############################## 20 | ###### STAGE: CONTAINER ###### 21 | ############################## 22 | FROM alpine 23 | 24 | COPY --from=build-env /tlssocksproxy /usr/sbin/tlssocksproxy 25 | 26 | ENTRYPOINT [ "/usr/sbin/tlssocksproxy" ] 27 | 28 | CMD ["/usr/sbin/tlssocksproxy"] 29 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/foomo/tlssocks 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 // indirect 7 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 8 | github.com/foomo/htpasswd v0.0.0-20200116085101-e3a90e78da9c 9 | github.com/google/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252 10 | github.com/patrickmn/go-cache v2.1.0+incompatible 11 | github.com/prometheus/client_golang v1.9.0 12 | github.com/prometheus/common v0.17.0 // indirect 13 | github.com/prometheus/procfs v0.6.0 // indirect 14 | github.com/spaolacci/murmur3 v1.1.0 15 | github.com/stretchr/testify v1.6.1 // indirect 16 | go.uber.org/multierr v1.6.0 // indirect 17 | go.uber.org/zap v1.16.0 18 | golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 19 | golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 // indirect 20 | golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 // indirect 21 | google.golang.org/protobuf v1.25.0 // indirect 22 | gopkg.in/yaml.v2 v2.4.0 23 | ) 24 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 4 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 5 | github.com/GehirnInc/crypt v0.0.0-20190301055215-6c0105aabd46/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= 6 | github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 h1:KeNholpO2xKjgaaSyd+DyQRrsQjhbSeS7qe4nEw8aQw= 7 | github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= 8 | github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= 9 | github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= 10 | github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 11 | github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 12 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 13 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 14 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 15 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 16 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 17 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 18 | github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 19 | github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 20 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 21 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 22 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 23 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 24 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 25 | github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= 26 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= 27 | github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 28 | github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 29 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 30 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 31 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 32 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 33 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 34 | github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= 35 | github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 36 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 37 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 38 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 39 | github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 40 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 41 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= 42 | github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 43 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 44 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 45 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 46 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 47 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 48 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 49 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 50 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 51 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 52 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 53 | github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 54 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= 55 | github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 56 | github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 57 | github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= 58 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 59 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 60 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 61 | github.com/foomo/htpasswd v0.0.0-20200116085101-e3a90e78da9c h1:DBGU7zCwrrPPDsD6+gqKG8UfMxenWg9BOJE/Nmfph+4= 62 | github.com/foomo/htpasswd v0.0.0-20200116085101-e3a90e78da9c/go.mod h1:SHawtolbB0ZOFoRWgDwakX5WpwuIWAK88bUXVZqK0Ss= 63 | github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= 64 | github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= 65 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 66 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 67 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 68 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 69 | github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= 70 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 71 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 72 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 73 | github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 74 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 75 | github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= 76 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 77 | github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 78 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 79 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 80 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 81 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 82 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 83 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 84 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 85 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 86 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 87 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 88 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 89 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 90 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 91 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 92 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 93 | github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 94 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 95 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 96 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 97 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 98 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 99 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 100 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 101 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 102 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 103 | github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= 104 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 105 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 106 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 107 | github.com/google/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252 h1:tAkooHvRrtO8kFB6YOPTpLQok3Hfv1DNDXdNqgi29Ao= 108 | github.com/google/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= 109 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 110 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 111 | github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= 112 | github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 113 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 114 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 115 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 116 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 117 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 118 | github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= 119 | github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= 120 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 121 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 122 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 123 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 124 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 125 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= 126 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 127 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 128 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 129 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 130 | github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 131 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 132 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 133 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 134 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 135 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 136 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 137 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 138 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 139 | github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= 140 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 141 | github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 142 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 143 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 144 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 145 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 146 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 147 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 148 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 149 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 150 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 151 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 152 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 153 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 154 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 155 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 156 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 157 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 158 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 159 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 160 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 161 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 162 | github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= 163 | github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= 164 | github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= 165 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 166 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 167 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 168 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 169 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 170 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 171 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 172 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 173 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 174 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 175 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 176 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 177 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 178 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 179 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 180 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 181 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 182 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 183 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 184 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 185 | github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= 186 | github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= 187 | github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= 188 | github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= 189 | github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 190 | github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 191 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 192 | github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= 193 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 194 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 195 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 196 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 197 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 198 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= 199 | github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= 200 | github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 201 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 202 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 203 | github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= 204 | github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= 205 | github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= 206 | github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= 207 | github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= 208 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 209 | github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= 210 | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= 211 | github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= 212 | github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 213 | github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 214 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 215 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 216 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 217 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 218 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 219 | github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 220 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 221 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 222 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 223 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 224 | github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= 225 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 226 | github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= 227 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 228 | github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= 229 | github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= 230 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 231 | github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 232 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 233 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 234 | github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 235 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 236 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 237 | github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 238 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 239 | github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 240 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 241 | github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= 242 | github.com/prometheus/common v0.17.0 h1:kDIZLI74SS+3tedSvEkykgBkD7txMxaJAPj8DtJUKYA= 243 | github.com/prometheus/common v0.17.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= 244 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 245 | github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 246 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 247 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 248 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 249 | github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 250 | github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= 251 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 252 | github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 253 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 254 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 255 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 256 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 257 | github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= 258 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 259 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 260 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 261 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 262 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 263 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 264 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 265 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 266 | github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 267 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 268 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 269 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 270 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 271 | github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 272 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 273 | github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 274 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 275 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 276 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 277 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 278 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 279 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 280 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 281 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 282 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 283 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 284 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 285 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 286 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 287 | go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 288 | go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 289 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 290 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 291 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 292 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 293 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 294 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 295 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 296 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 297 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 298 | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 299 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 300 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 301 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 302 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 303 | go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= 304 | go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= 305 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 306 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 307 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 308 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 309 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 310 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 311 | golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 312 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 313 | golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= 314 | golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 315 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 316 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 317 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 318 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 319 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 320 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 321 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 322 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 323 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 324 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 325 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 326 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 327 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 328 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 329 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 330 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 331 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 332 | golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 333 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 334 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 335 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 336 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 337 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 338 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 339 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 340 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 341 | golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= 342 | golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 343 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 344 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 345 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 346 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 347 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 348 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 349 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 350 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 351 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 352 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 353 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 354 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 355 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 356 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 357 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 358 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 359 | golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 360 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 361 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 362 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 363 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 364 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 365 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 366 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 367 | golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 368 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 369 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 370 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 371 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 372 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 373 | golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 374 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 375 | golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= 376 | golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 377 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 378 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 379 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 380 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 381 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 382 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 383 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 384 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 385 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 386 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 387 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 388 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 389 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 390 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 391 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 392 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 393 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 394 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 395 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 396 | golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE= 397 | golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 398 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 399 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 400 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 401 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 402 | google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 403 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 404 | google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 405 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 406 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 407 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 408 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 409 | google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 410 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 411 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 412 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 413 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 414 | google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= 415 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 416 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 417 | google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 418 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 419 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 420 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 421 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 422 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 423 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 424 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 425 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 426 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 427 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 428 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 429 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 430 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 431 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 432 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 433 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 434 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 435 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 436 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 437 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 438 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 439 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 440 | gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= 441 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 442 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 443 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 444 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 445 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 446 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 447 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 448 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 449 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 450 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 451 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 452 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 453 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 454 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 455 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 456 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 457 | honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= 458 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 459 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 460 | sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= 461 | --------------------------------------------------------------------------------