├── .gitignore ├── client.go ├── cache.go ├── go.mod ├── Makefile ├── .goreleaser.yml ├── config.sample.toml ├── config.go ├── dnscrypt_client.go ├── doh_client.go ├── README.md ├── dot_client.go ├── main.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | danse 3 | config.toml 4 | dist/ 5 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/miekg/dns" 4 | 5 | type DNSClient interface { 6 | GetDNSResponse(m *dns.Msg) (*dns.Msg, error) 7 | } 8 | -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/miekg/dns" 7 | ) 8 | 9 | // DNSInCache is serialized and stored in the cache 10 | type DNSInCache struct { 11 | Msg *dns.Msg 12 | CreatedAt time.Time 13 | } 14 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/iamd3vil/danse 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ameshkov/dnscrypt/v2 v2.2.1 7 | github.com/hashicorp/golang-lru v0.5.4 8 | github.com/knadh/koanf v1.2.0 9 | github.com/miekg/dns v1.1.43 10 | ) 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN := danse 2 | DIR := dist 3 | GOBIN := go 4 | 5 | LAST_COMMIT := $(shell git rev-parse --short HEAD) 6 | LAST_COMMIT_DATE := $(shell git show -s --format=%ci ${LAST_COMMIT}) 7 | VERSION := $(shell git describe --tags) 8 | BUILDSTR := ${VERSION} (Commit: ${LAST_COMMIT_DATE} (${LAST_COMMIT}), Build: $(shell date +"%Y-%m-%d% %H:%M:%S %z")) 9 | 10 | .PHONY: build 11 | build: 12 | mkdir -p ${DIR} 13 | CGO_ENABLED=0 ${GOBIN} build -o ${DIR}/${BIN} --ldflags="-X 'main.buildString=${BUILDSTR}'" 14 | cp ${DIR}/${BIN} . 15 | 16 | run: build 17 | ./${DIR}/${BIN} -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod download 4 | builds: 5 | - env: 6 | - CGO_ENABLED=0 7 | goos: 8 | - freebsd 9 | - linux 10 | - darwin 11 | goarch: 12 | - amd64 13 | - arm 14 | - arm64 15 | goarm: 16 | - 6 17 | - 7 18 | archives: 19 | - replacements: 20 | darwin: Darwin 21 | linux: Linux 22 | freebsd: FreeBSD 23 | 386: i386 24 | amd64: x86_64 25 | arm: arm 26 | arm64: arm64 27 | release: 28 | github: 29 | owner: iamd3vil 30 | name: danse 31 | checksum: 32 | name_template: 'checksums.txt' 33 | snapshot: 34 | name_template: "{{ .Tag }}-next" 35 | changelog: 36 | sort: asc 37 | filters: 38 | exclude: 39 | - '^docs:' 40 | - '^test:' -------------------------------------------------------------------------------- /config.sample.toml: -------------------------------------------------------------------------------- 1 | # Address for danse to listen on. 2 | bind_address = "127.0.0.1:5454" 3 | 4 | # Only used for resolving resolver url. No queries received by danse will be sent here. Default is 9.9.9.9:53 5 | bootstrap_address = "1.1.1.1:53" 6 | 7 | # Urls for resolvers. 8 | [resolver] 9 | 10 | # Type of resolver. Can be doh or dot or dnscrypt. 11 | type = "doh" 12 | 13 | # Resolver URLs. 14 | urls = ["https://dns.quad9.net/dns-query", "https://cloudflare-dns.com/dns-query"] 15 | 16 | 17 | [cache] 18 | # Should the answers be cached according to ttl. Default is true. 19 | cache = true 20 | 21 | # Maximum records to cache. 22 | max_items = 10000 23 | 24 | # Config for logging 25 | [log] 26 | # Log level 27 | log_level = "info" 28 | 29 | # Logs all queries to stdout. Default is false. 30 | log_queries = true -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/knadh/koanf" 5 | "github.com/knadh/koanf/parsers/toml" 6 | "github.com/knadh/koanf/providers/confmap" 7 | "github.com/knadh/koanf/providers/file" 8 | ) 9 | 10 | type cfgResolver struct { 11 | Type string `koanf:"type"` 12 | Urls []string `koanf:"urls"` 13 | } 14 | 15 | type cfgCache struct { 16 | Cache bool `koanf:"cache"` 17 | MaxItems int `koanf:"max_items"` 18 | } 19 | 20 | type cfgLog struct { 21 | LogLevel string `koanf:"log_level"` 22 | LogQueries bool `koanf:"log_queries"` 23 | } 24 | 25 | type Config struct { 26 | BindAddress string `koanf:"bind_address"` 27 | BootstrapAddress string `koanf:"bootstrap_address"` 28 | Cache cfgCache `koanf:"cache"` 29 | Resolver cfgResolver `koanf:"resolver"` 30 | Log cfgLog `koanf:"log"` 31 | } 32 | 33 | func initConfig(cfgPath string) (Config, error) { 34 | k := koanf.New(".") 35 | 36 | // Set default values 37 | k.Load(confmap.Provider(map[string]interface{}{ 38 | "cache.cache": true, 39 | "bind_address": "127.0.0.1:53", 40 | "bootstrap_address": "9.9.9.9:53", 41 | "resolver.type": "doh", 42 | }, "."), nil) 43 | 44 | if err := k.Load(file.Provider(cfgPath), toml.Parser()); err != nil { 45 | return Config{}, err 46 | } 47 | 48 | cfg := Config{} 49 | 50 | if err := k.Unmarshal("", &cfg); err != nil { 51 | return Config{}, err 52 | } 53 | 54 | return cfg, nil 55 | } 56 | -------------------------------------------------------------------------------- /dnscrypt_client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "sync" 6 | "time" 7 | 8 | "github.com/ameshkov/dnscrypt/v2" 9 | "github.com/miekg/dns" 10 | ) 11 | 12 | type DCryptClient struct { 13 | client *dnscrypt.Client 14 | resolverInfos []*dnscrypt.ResolverInfo 15 | 16 | // Last used index 17 | lIndex int 18 | 19 | logQueries bool 20 | 21 | sync.Mutex 22 | } 23 | 24 | func (c *DCryptClient) GetDNSResponse(msg *dns.Msg) (*dns.Msg, error) { 25 | if len(msg.Question) == 0 { 26 | return nil, nil 27 | } 28 | 29 | c.Lock() 30 | 31 | rinfo := c.resolverInfos[c.lIndex] 32 | 33 | // Increase last index 34 | c.lIndex++ 35 | 36 | if c.lIndex == len(c.resolverInfos) { 37 | c.lIndex = 0 38 | } 39 | 40 | c.Unlock() 41 | 42 | if c.logQueries { 43 | log.Printf("Sending to %s for query: %s", rinfo.ProviderName, msg.Question[0].String()) 44 | } 45 | return c.client.Exchange(msg, rinfo) 46 | } 47 | 48 | func NewDNSCryptClient(stamps []string, logQueries bool) (*DCryptClient, error) { 49 | c := dnscrypt.Client{ 50 | Net: "udp", 51 | Timeout: 10 * time.Second, 52 | } 53 | client := DCryptClient{ 54 | client: &c, 55 | resolverInfos: make([]*dnscrypt.ResolverInfo, 0, len(stamps)), 56 | logQueries: logQueries, 57 | } 58 | 59 | for _, stamp := range stamps { 60 | resolverInfo, err := c.Dial(stamp) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | client.resolverInfos = append(client.resolverInfos, resolverInfo) 66 | } 67 | 68 | return &client, nil 69 | } 70 | -------------------------------------------------------------------------------- /doh_client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "sync" 10 | 11 | "github.com/miekg/dns" 12 | ) 13 | 14 | type DohClient struct { 15 | httpClient *http.Client 16 | 17 | // Slice of URLs 18 | urls []string 19 | 20 | // Last used index 21 | lIndex int 22 | 23 | logQueries bool 24 | 25 | sync.Mutex 26 | } 27 | 28 | func (c *DohClient) GetDNSResponse(msg *dns.Msg) (*dns.Msg, error) { 29 | b, err := msg.Pack() 30 | if err != nil { 31 | return &dns.Msg{}, err 32 | } 33 | 34 | c.Lock() 35 | 36 | url := c.urls[c.lIndex] 37 | 38 | // Increase last index 39 | c.lIndex++ 40 | 41 | if c.lIndex == len(c.urls) { 42 | c.lIndex = 0 43 | } 44 | 45 | c.Unlock() 46 | 47 | if c.logQueries { 48 | log.Printf("Sending to %s for query: %s", url, msg.Question[0].String()) 49 | } 50 | 51 | resp, err := c.httpClient.Post(url, "application/dns-message", bytes.NewBuffer(b)) 52 | if err != nil { 53 | return &dns.Msg{}, err 54 | } 55 | if resp.StatusCode != http.StatusOK { 56 | log.Printf("Response from DOH provider has status code: %d", resp.StatusCode) 57 | return &dns.Msg{}, errors.New("error from DOH provider") 58 | } 59 | 60 | body, err := ioutil.ReadAll(resp.Body) 61 | if err != nil { 62 | return &dns.Msg{}, nil 63 | } 64 | 65 | r := &dns.Msg{} 66 | err = r.Unpack(body) 67 | 68 | return r, err 69 | } 70 | 71 | func NewDOHClient(c *http.Client, urls []string, logQueries bool) (*DohClient, error) { 72 | return &DohClient{ 73 | httpClient: c, 74 | urls: urls, 75 | logQueries: logQueries, 76 | }, nil 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Danse 2 | 3 | Danse is a DNS resolver which receives packets over conventional DNS(UDP) and resolves it by talking to another resolver over DNS over HTTPS(DoH) or DNS Over TLS(DoT) or DNSCrypt. DoH/DoT/DNSCrypt would reduce any snooping by ISP or any middlemen since the requests would be encrypted. 4 | 5 | This would allow any application which doesn't support DoH/DoT/DNSCrypt still use DoH/DoT/DNSCrypt. Danse is supposed to be run locally or on a local network. There is no point running this over internet since DNS queries then wouldn't be encrypted between your device and Danse. 6 | 7 | ## Usage 8 | 9 | ```shell 10 | $ danse -config /etc/danse/config.toml 11 | ``` 12 | 13 | Sample config: 14 | 15 | ```toml 16 | # Address for danse to listen on. 17 | bind_address = "127.0.0.1:5454" 18 | 19 | # Only used for resolving resolver url. No queries received by danse will be sent here. Default is 9.9.9.9:53 20 | bootstrap_address = "1.1.1.1:53" 21 | 22 | # Urls for resolvers. 23 | [resolver] 24 | 25 | # Type of resolver. Can be doh or dot or dnscrypt. 26 | type = "doh" 27 | 28 | # Resolver URLs. 29 | urls = ["https://dns.quad9.net/dns-query", "https://cloudflare-dns.com/dns-query"] 30 | 31 | 32 | [cache] 33 | # Should the answers be cached according to ttl. Default is true. 34 | cache = true 35 | 36 | # Maximum records to cache. 37 | max_items = 10000 38 | 39 | # Config for logging 40 | [log] 41 | # Log level 42 | log_level = "info" 43 | 44 | # Logs all queries to stdout. Default is false. 45 | log_queries = true 46 | ``` 47 | 48 | A sample config file with all the fields can be found at `config.sample.toml`. 49 | 50 | ## TODO 51 | 52 | - [X] Caching 53 | - [X] Load Balance to multiple DoH providers for improved privacy 54 | - [X] Option to log queries 55 | - [X] Option to provide a bootstrap DNS server for resolving the given urls 56 | - [X] Support for Dns Over TLS -------------------------------------------------------------------------------- /dot_client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "sync" 7 | 8 | "github.com/miekg/dns" 9 | ) 10 | 11 | type DOTClient struct { 12 | urls []string 13 | conns map[string]*dns.Conn 14 | client *dns.Client 15 | 16 | // Last used index 17 | lIndex int 18 | 19 | logQueries bool 20 | sync.Mutex 21 | } 22 | 23 | func (c *DOTClient) GetDNSResponse(msg *dns.Msg) (*dns.Msg, error) { 24 | c.Lock() 25 | 26 | url := c.urls[c.lIndex] 27 | 28 | // Increase last index 29 | c.lIndex++ 30 | 31 | if c.lIndex == len(c.urls) { 32 | c.lIndex = 0 33 | } 34 | 35 | c.Unlock() 36 | 37 | log.Printf("log queries: %v", c.logQueries) 38 | 39 | if c.logQueries { 40 | log.Printf("Sending to %s for query: %s", url, msg.Question[0].String()) 41 | } 42 | 43 | var r *dns.Msg 44 | 45 | var makeconn bool 46 | for i := 0; i < 5; i++ { 47 | conn, err := c.getConn(url, makeconn) 48 | if err != nil { 49 | return &dns.Msg{}, err 50 | } 51 | 52 | r, _, err = c.client.ExchangeWithConn(msg, conn) 53 | if err != nil { 54 | makeconn = true 55 | continue 56 | } 57 | break 58 | } 59 | return r, nil 60 | } 61 | 62 | func (c *DOTClient) getConn(url string, makeconn bool) (*dns.Conn, error) { 63 | c.Lock() 64 | defer c.Unlock() 65 | 66 | if conn, ok := c.conns[url]; ok { 67 | if makeconn { 68 | goto makeConn 69 | } 70 | return conn, nil 71 | } 72 | 73 | makeConn: 74 | conn, err := c.client.Dial(url) 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | c.conns[url] = conn 80 | return conn, nil 81 | } 82 | 83 | func NewDOTClient(urls []string, dialer *net.Dialer, logQueries bool) (*DOTClient, error) { 84 | return &DOTClient{ 85 | urls: urls, 86 | client: &dns.Client{ 87 | Net: "tcp-tls", 88 | Dialer: dialer, 89 | }, 90 | conns: map[string]*dns.Conn{}, 91 | logQueries: logQueries, 92 | }, nil 93 | } 94 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "math" 9 | "net" 10 | "net/http" 11 | "os" 12 | "time" 13 | 14 | lru "github.com/hashicorp/golang-lru" 15 | "github.com/miekg/dns" 16 | ) 17 | 18 | var buildString string 19 | 20 | type env struct { 21 | cache *lru.Cache 22 | cfg Config 23 | client DNSClient 24 | } 25 | 26 | func main() { 27 | cfgPath := flag.String("config", "config.toml", "Path to config file") 28 | version := flag.Bool("version", false, "Version") 29 | flag.Parse() 30 | 31 | if *version { 32 | fmt.Println(buildString) 33 | os.Exit(0) 34 | } 35 | 36 | cfg, err := initConfig(*cfgPath) 37 | if err != nil { 38 | log.Fatalf("error reading config: %v", err) 39 | } 40 | 41 | maxCacheItems := 512 42 | if cfg.Cache.MaxItems != 0 { 43 | maxCacheItems = cfg.Cache.MaxItems 44 | } 45 | 46 | e := env{ 47 | cfg: cfg, 48 | } 49 | 50 | // Initialize cache 51 | if cfg.Cache.Cache { 52 | cache, err := lru.New(maxCacheItems) 53 | if err != nil { 54 | log.Fatalln("Couldn't create cache: ", err) 55 | } 56 | 57 | e.cache = cache 58 | } 59 | 60 | // Make a dialer which resolves url with bootstrap address. 61 | dialer := &net.Dialer{ 62 | Resolver: &net.Resolver{ 63 | PreferGo: true, 64 | Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 65 | d := net.Dialer{ 66 | Timeout: 5 * time.Second, 67 | } 68 | return d.DialContext(ctx, "udp", cfg.BootstrapAddress) 69 | }, 70 | }, 71 | } 72 | 73 | dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) { 74 | return dialer.DialContext(ctx, network, addr) 75 | } 76 | 77 | var ( 78 | client DNSClient 79 | ) 80 | 81 | switch cfg.Resolver.Type { 82 | case "doh": 83 | client, err = getDOHDnsClient(dialContext, cfg) 84 | if err != nil { 85 | log.Fatalf("Couldn't create DNS client: %v", err) 86 | } 87 | 88 | e.client = client 89 | case "dot": 90 | client, err = NewDOTClient(cfg.Resolver.Urls, dialer, cfg.Log.LogQueries) 91 | if err != nil { 92 | log.Fatalf("Couldn't create DNS client: %v", err) 93 | } 94 | 95 | e.client = client 96 | case "dnscrypt": 97 | client, err := NewDNSCryptClient(cfg.Resolver.Urls, cfg.Log.LogQueries) 98 | if err != nil { 99 | log.Fatalf("Couldn't create DNSCrypt client: %v", err) 100 | } 101 | 102 | e.client = client 103 | } 104 | 105 | // Start the DNS server. 106 | dnsServer := &dns.Server{Addr: cfg.BindAddress, Net: "udp"} 107 | 108 | dns.HandleFunc(".", e.handleDNS) 109 | 110 | log.Fatalln(dnsServer.ListenAndServe()) 111 | } 112 | 113 | func (e *env) handleDNS(w dns.ResponseWriter, r *dns.Msg) { 114 | if len(r.Question) == 0 { 115 | return 116 | } 117 | 118 | if e.cfg.Log.LogQueries { 119 | log.Println("Got DNS query for ", r.Question[0].String()) 120 | } 121 | 122 | cacheKey := r.Question[0].String() 123 | // Check if we should check cache or not 124 | if !e.cfg.Cache.Cache { 125 | e.getAndSendResponse(w, r, cacheKey) 126 | return 127 | } 128 | 129 | // Check if the key is already in cache 130 | val, ok := e.cache.Get(cacheKey) 131 | if !ok { 132 | e.getAndSendResponse(w, r, cacheKey) 133 | return 134 | } 135 | 136 | cResp := val.(DNSInCache) 137 | 138 | // Check if this record is expired 139 | ttl := minTTL(cResp.Msg) 140 | 141 | if time.Since(cResp.CreatedAt) > ttl { 142 | e.getAndSendResponse(w, r, cacheKey) 143 | return 144 | } 145 | 146 | resp := cResp.Msg 147 | 148 | resp.MsgHdr.Id = r.MsgHdr.Id 149 | 150 | w.WriteMsg(adjustTTL(resp, cResp.CreatedAt)) 151 | } 152 | 153 | func (e *env) getAndSendResponse(w dns.ResponseWriter, r *dns.Msg, cacheKey string) { 154 | respMsg, err := e.client.GetDNSResponse(r) 155 | if err != nil { 156 | log.Printf("Something wrong with resp: %v", err) 157 | return 158 | } 159 | 160 | // Put it in cache 161 | if e.cfg.Cache.Cache { 162 | dnsCache := DNSInCache{Msg: respMsg, CreatedAt: time.Now()} 163 | e.cache.Add(cacheKey, dnsCache) 164 | } 165 | 166 | w.WriteMsg(respMsg) 167 | } 168 | 169 | func minTTL(m *dns.Msg) time.Duration { 170 | if len(m.Answer) >= 1 { 171 | ttl := m.Answer[0].Header().Ttl 172 | for _, a := range m.Answer { 173 | if a.Header().Ttl < ttl { 174 | ttl = a.Header().Ttl 175 | } 176 | } 177 | return time.Duration(ttl) * time.Second 178 | } 179 | return 0 180 | } 181 | 182 | func adjustTTL(m *dns.Msg, createdAt time.Time) *dns.Msg { 183 | adj := *m 184 | for i := 0; i < len(m.Answer); i++ { 185 | expiresAt := createdAt.Add(time.Duration(m.Answer[i].Header().Ttl) * time.Second) 186 | ttl := math.Round(time.Until(expiresAt).Seconds()) 187 | adj.Answer[i].Header().Ttl = uint32(ttl) 188 | } 189 | return &adj 190 | } 191 | 192 | func getDOHDnsClient(dialContext func(ctx context.Context, network string, addr string) (net.Conn, error), cfg Config) (DNSClient, error) { 193 | transport := http.DefaultTransport.(*http.Transport) 194 | transport.DialContext = dialContext 195 | 196 | httpClient := &http.Client{ 197 | Timeout: 10 * time.Second, 198 | Transport: transport, 199 | } 200 | 201 | return NewDOHClient(httpClient, cfg.Resolver.Urls, cfg.Log.LogQueries) 202 | } 203 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= 3 | github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= 4 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 5 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 6 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= 7 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= 8 | github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw= 9 | github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us= 10 | github.com/ameshkov/dnscrypt/v2 v2.2.1 h1:+cApRxzeBZqjUNsN26TTz7r5A8U+buON3kJgIYE3QWQ= 11 | github.com/ameshkov/dnscrypt/v2 v2.2.1/go.mod h1:+8SbPbVXpxxcUsgGi8eodkqWPo1MyNHxKYC8hDpqLSo= 12 | github.com/ameshkov/dnsstamps v1.0.1 h1:LhGvgWDzhNJh+kBQd/AfUlq1vfVe109huiXw4JhnPug= 13 | github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A= 14 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 15 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 16 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 17 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 18 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 19 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 20 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 22 | github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= 23 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 24 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 25 | github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= 26 | github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 27 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 28 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 29 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 30 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 31 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 32 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 33 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 34 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 35 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 36 | github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= 37 | github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= 38 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 39 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 40 | github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= 41 | github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= 42 | github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 43 | github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 44 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 45 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 46 | github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 47 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 48 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 49 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 50 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 51 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 52 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 53 | github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= 54 | github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= 55 | github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 56 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 57 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 58 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 59 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 60 | github.com/knadh/koanf v1.2.0 h1:fANR65nD9cI3HGm0s3pmzqh4hkknt4TasmZzh+rLy1M= 61 | github.com/knadh/koanf v1.2.0/go.mod h1:xpPTwMhsA/aaQLAilyCCqfpEiY1gpa160AiCuWHJUjY= 62 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 63 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 64 | github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 65 | github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= 66 | github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= 67 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 68 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 69 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 70 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 71 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 72 | github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 73 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 74 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 75 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 76 | github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= 77 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 78 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 79 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 80 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 81 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 82 | github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 83 | github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= 84 | github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= 85 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 86 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 87 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 88 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 89 | github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= 90 | github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 91 | github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 92 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 93 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 94 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 95 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 96 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 97 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 98 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 99 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 100 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 101 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 102 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 103 | golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= 104 | golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 105 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 106 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 107 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 108 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 109 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 110 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 111 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 112 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 113 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 114 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 115 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 116 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 117 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 118 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 119 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 120 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 121 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 122 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 123 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 124 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 125 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 126 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 127 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 128 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 129 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 130 | golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 131 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 132 | golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 133 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 134 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 135 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 136 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 137 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 138 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 139 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g= 140 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 141 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 142 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 143 | golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 144 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 145 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 146 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 147 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 148 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 149 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 150 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 151 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 152 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 153 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 154 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 155 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 156 | google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 157 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 158 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 159 | google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 160 | gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= 161 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 162 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 163 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 164 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 165 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 166 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 167 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 168 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 169 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 170 | --------------------------------------------------------------------------------