From b07f284471ec8a6912fd5605173d748907b08ed0 Mon Sep 17 00:00:00 2001 From: Tyk-ITS Account <92926870+Tyk-ITS@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:51:57 +0100 Subject: [PATCH 01/33] [CI] Sync automation: Syncing commits from master Picking CI changes from the commit d85facdadef2ee95b817d2695fb10935664f5b9b --- .github/dependabot.yml | 2 +- .github/workflows/api-tests.yml | 1 + .github/workflows/del-env.yml | 2 +- .github/workflows/release.yml | 4 +- ci/Dockerfile.std | 2 +- ci/aws/byol.pkr.hcl | 2 +- ci/goreleaser/goreleaser-el7.yml | 148 ------------------------------- ci/goreleaser/goreleaser.yml | 2 +- ci/install/before_install.sh | 2 +- ci/install/post_install.sh | 2 +- ci/install/post_remove.sh | 2 +- ci/install/post_trans.sh | 2 +- ci/terraform/outputs.tf | 2 +- 13 files changed, 13 insertions(+), 160 deletions(-) delete mode 100644 ci/goreleaser/goreleaser-el7.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fd58ebf9fca..a7541ed5a74 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 version: 2 updates: diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 1ed41907ee0..d9b6d60d2d2 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -131,6 +131,7 @@ jobs: run: | pytest working-directory: tyk-automated-tests + timeout-minutes: 30 - name: Archive Integration tests report if: ${{ always() }} diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml index 4f212291000..e404d8564a8 100644 --- a/.github/workflows/del-env.yml +++ b/.github/workflows/del-env.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 name: Retiring dev env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de4dc54c283..d86dd4db19f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 # Distribution channels covered by this workflow @@ -123,7 +123,7 @@ jobs: - uses: goreleaser/goreleaser-action@v4 with: version: latest - args: release --clean -f ${{ matrix.goreleaser }} ${{ !startsWith(github.ref, 'refs/tags/') && ' --snapshot' }} + args: release --clean -f ${{ matrix.goreleaser }} ${{ !startsWith(github.ref, 'refs/tags/') && ' --snapshot' || '' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CGO_ENABLED: 1 diff --git a/ci/Dockerfile.std b/ci/Dockerfile.std index fb9f0eaf64e..eeaf8d4a527 100644 --- a/ci/Dockerfile.std +++ b/ci/Dockerfile.std @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 FROM debian:bullseye-slim ARG TARGETARCH diff --git a/ci/aws/byol.pkr.hcl b/ci/aws/byol.pkr.hcl index d0b89db7992..e04276a60ce 100644 --- a/ci/aws/byol.pkr.hcl +++ b/ci/aws/byol.pkr.hcl @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 packer { required_plugins { diff --git a/ci/goreleaser/goreleaser-el7.yml b/ci/goreleaser/goreleaser-el7.yml deleted file mode 100644 index e0a09434fcb..00000000000 --- a/ci/goreleaser/goreleaser-el7.yml +++ /dev/null @@ -1,148 +0,0 @@ -# Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 - -# Check the documentation at http://goreleaser.com -# This project needs CGO_ENABLED=1 and the cross-compiler toolchains for -# - arm64 -# - amd64 - -builds: - - id: std-linux - flags: - - -tags=goplugin - ldflags: - - -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser - goos: - - linux - goarch: - - amd64 - binary: tyk - - id: std-arm64 - flags: - - -tags=goplugin - ldflags: - - -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser - env: - - CC=aarch64-linux-gnu-gcc - goos: - - linux - goarch: - - arm64 - binary: tyk - -nfpms: - - id: std - vendor: "Tyk Technologies Ltd" - homepage: "https://tyk.io" - maintainer: "Tyk " - description: Tyk Open Source API Gateway written in Go, supporting REST, GraphQL, TCP and gRPC protocols - package_name: tyk-gateway - builds: - - std-linux - - std-arm64 - formats: - - deb - - rpm - contents: - - src: "README.md" - dst: "/opt/share/docs/tyk-gateway/README.md" - - src: "ci/install/*" - dst: "/opt/tyk-gateway/install" - - src: ci/install/inits/systemd/system/tyk-gateway.service - dst: /lib/systemd/system/tyk-gateway.service - - src: ci/install/inits/sysv/init.d/tyk-gateway - dst: /etc/init.d/tyk-gateway - - src: /opt/tyk-gateway - dst: /opt/tyk - type: "symlink" - - src: "LICENSE.md" - dst: "/opt/share/docs/tyk-gateway/LICENSE.md" - - src: "apps/app_sample.*" - dst: "/opt/tyk-gateway/apps" - - src: "templates/*.json" - dst: "/opt/tyk-gateway/templates" - - src: "templates/playground/*" - dst: "/opt/tyk-gateway/templates/playground" - - src: "middleware/*.js" - dst: "/opt/tyk-gateway/middleware" - - src: "event_handlers/sample/*.js" - dst: "/opt/tyk-gateway/event_handlers/sample" - - src: "policies/*.json" - dst: "/opt/tyk-gateway/policies" - - src: "coprocess/*" - dst: "/opt/tyk-gateway/coprocess" - - src: tyk.conf.example - dst: /opt/tyk-gateway/tyk.conf - type: "config|noreplace" - scripts: - preinstall: "ci/install/before_install.sh" - postinstall: "ci/install/post_install.sh" - postremove: "ci/install/post_remove.sh" - bindir: "/opt/tyk-gateway" - overrides: - rpm: - file_name_template: '{{ .PackageName }}-{{ replace .Version "-" "~" }}-1.{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}' - replacements: - amd64: x86_64 - arm: aarch64 - arm64: aarch64 - deb: - file_name_template: '{{ .PackageName }}_{{ replace .Version "-" "~" }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}' - replacements: - arm: arm64 - rpm: - scripts: - posttrans: ci/install/post_trans.sh - signature: - key_file: tyk.io.signing.key - deb: - signature: - key_file: tyk.io.signing.key - type: origin - -publishers: - - name: tyk-gateway-unstable - env: - - PACKAGECLOUD_TOKEN={{ .Env.PACKAGECLOUD_TOKEN }} - - REPO=tyk/tyk-gateway-unstable - - RPMVERS={{ .Env.RPMVERS }} - - DEBVERS={{ .Env.DEBVERS }} - cmd: /pc.sh {{ .ArtifactPath }} - - -# This disables archives -archives: - - format: binary - allow_different_binary_count: true -dockers: -# Build plugin-compiler -- ids: - - std - image_templates: - - tykio/tyk-plugin-compiler:{{ .Tag }}-el7 - - tykio/tyk-plugin-compiler:v{{ .Major }}.{{ .Minor }}{{.Prerelease}}-el7 - build_flag_templates: - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title=tyk-plugin-compiler" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--build-arg=TYK_GW_TAG={{ .Tag }}" - - "--build-arg=GOLANG_CROSS={{ .Env.GOLANG_CROSS }}" - - "--build-arg=GITHUB_SHA={{ .Env.GITHUB_SHA }}" - goarch: amd64 - goos: linux - dockerfile: ci/images/plugin-compiler/Dockerfile - extra_files: - - ci/images/plugin-compiler - -checksum: - disable: true - -release: - disable: true - github: - owner: TykTechnologies - name: tyk - prerelease: auto - draft: true - name_template: "{{.ProjectName}}-v{{.Version}}" diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index f747136ac47..58d4213719e 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -1,5 +1,5 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 # Check the documentation at http://goreleaser.com # This project needs CGO_ENABLED=1 and the cross-compiler toolchains for diff --git a/ci/install/before_install.sh b/ci/install/before_install.sh index e70c7d13d53..b2ec5a36463 100755 --- a/ci/install/before_install.sh +++ b/ci/install/before_install.sh @@ -1,7 +1,7 @@ #!/bin/bash # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 echo "Creating user and group..." GROUPNAME="tyk" diff --git a/ci/install/post_install.sh b/ci/install/post_install.sh index cb668552289..ec8795a612a 100755 --- a/ci/install/post_install.sh +++ b/ci/install/post_install.sh @@ -2,7 +2,7 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 # If "True" the install directory ownership will be changed to "tyk:tyk" change_ownership="False" diff --git a/ci/install/post_remove.sh b/ci/install/post_remove.sh index d5cf2ad3a5b..12e1dc275cd 100755 --- a/ci/install/post_remove.sh +++ b/ci/install/post_remove.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 cleanRemove() { diff --git a/ci/install/post_trans.sh b/ci/install/post_trans.sh index 00088d3b7ad..c3f730ffbf1 100644 --- a/ci/install/post_trans.sh +++ b/ci/install/post_trans.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 if command -V systemctl >/dev/null 2>&1; then if [ ! -f /lib/systemd/system/tyk-gateway.service ]; then diff --git a/ci/terraform/outputs.tf b/ci/terraform/outputs.tf index 7869f5d8d59..f2b5a39db0e 100644 --- a/ci/terraform/outputs.tf +++ b/ci/terraform/outputs.tf @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu May 11 05:45:55 UTC 2023 +# Generated on: Mon Jun 5 16:49:38 UTC 2023 From bec8fbdc6a417bd411baf22b8766f5ab6ff4c8e7 Mon Sep 17 00:00:00 2001 From: Tyk-ITS Account <92926870+Tyk-ITS@users.noreply.github.com> Date: Wed, 7 Jun 2023 08:47:51 +0100 Subject: [PATCH 02/33] [CI] Sync automation: Syncing commits from master Picking CI changes from the commit d161d2539c8094c4339aec6dbd694c7b46596f47 --- .github/dependabot.yml | 2 +- .github/workflows/del-env.yml | 2 +- .github/workflows/release.yml | 2 +- ci/Dockerfile.std | 2 +- ci/aws/byol.pkr.hcl | 2 +- ci/goreleaser/goreleaser.yml | 2 +- ci/images/plugin-compiler/Dockerfile | 21 +- .../plugin-compiler/data/basic-plugin/go.mod | 83 -- .../plugin-compiler/data/basic-plugin/go.sum | 1236 ----------------- ci/images/plugin-compiler/data/build.sh | 23 +- ci/images/plugin-compiler/data/test.sh | 5 + ci/install/before_install.sh | 2 +- ci/install/post_install.sh | 2 +- ci/install/post_remove.sh | 2 +- ci/install/post_trans.sh | 2 +- ci/terraform/outputs.tf | 2 +- 16 files changed, 49 insertions(+), 1341 deletions(-) delete mode 100644 ci/images/plugin-compiler/data/basic-plugin/go.sum diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a7541ed5a74..2a39ef51738 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 version: 2 updates: diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml index e404d8564a8..9e2d3aa0e04 100644 --- a/.github/workflows/del-env.yml +++ b/.github/workflows/del-env.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 name: Retiring dev env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d86dd4db19f..b6b2aaeb2e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 # Distribution channels covered by this workflow diff --git a/ci/Dockerfile.std b/ci/Dockerfile.std index eeaf8d4a527..8c4ee847841 100644 --- a/ci/Dockerfile.std +++ b/ci/Dockerfile.std @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 FROM debian:bullseye-slim ARG TARGETARCH diff --git a/ci/aws/byol.pkr.hcl b/ci/aws/byol.pkr.hcl index e04276a60ce..fe7ede36197 100644 --- a/ci/aws/byol.pkr.hcl +++ b/ci/aws/byol.pkr.hcl @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 packer { required_plugins { diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index 58d4213719e..ad9aa49c5e3 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -1,5 +1,5 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 # Check the documentation at http://goreleaser.com # This project needs CGO_ENABLED=1 and the cross-compiler toolchains for diff --git a/ci/images/plugin-compiler/Dockerfile b/ci/images/plugin-compiler/Dockerfile index 6b3ed7ebb78..7fa40e08b6a 100644 --- a/ci/images/plugin-compiler/Dockerfile +++ b/ci/images/plugin-compiler/Dockerfile @@ -1,26 +1,31 @@ ARG GOLANG_CROSS - FROM tykio/golang-cross:${GOLANG_CROSS} LABEL description="Image for plugin development" ENV TYK_GW_PATH=/go/src/github.com/TykTechnologies/tyk ENV GO111MODULE=on - # This directory will contain the plugin source and will be # mounted from the host box by the user using docker volumes ENV PLUGIN_SOURCE_PATH=/plugin-source RUN mkdir -p $TYK_GW_PATH $PLUGIN_SOURCE_PATH -COPY ci/images/plugin-compiler/data/build.sh /build.sh -RUN chmod +x /build.sh - RUN apt-get remove -y --allow-remove-essential --auto-remove mercurial \ && rm /usr/bin/passwd && rm /usr/sbin/adduser -RUN curl -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/TykTechnologies/tyk/tarball/$GITUHB_SHA --output - | tar --strip-components 1 -C $TYK_GW_PATH -xzf - -RUN cd $TYK_GW_PATH +ADD go.mod go.sum $TYK_GW_PATH +WORKDIR $TYK_GW_PATH +RUN go mod download -ENTRYPOINT ["/build.sh"] +ADD . $TYK_GW_PATH +ARG GITHUB_SHA +ARG GITHUB_TAG +ENV GITHUB_SHA ${GITHUB_SHA} +ENV GITHUB_TAG ${GITHUB_TAG} + +COPY ci/images/plugin-compiler/data/build.sh /build.sh +RUN chmod +x /build.sh + +ENTRYPOINT ["/build.sh"] diff --git a/ci/images/plugin-compiler/data/basic-plugin/go.mod b/ci/images/plugin-compiler/data/basic-plugin/go.mod index da8d53f2dd7..f0793995cc2 100644 --- a/ci/images/plugin-compiler/data/basic-plugin/go.mod +++ b/ci/images/plugin-compiler/data/basic-plugin/go.mod @@ -1,86 +1,3 @@ module example.com/basic-plugin go 1.19 - -require ( - github.com/TykTechnologies/tyk v1.9.2-0.20230419071249-a0633247127a - github.com/TykTechnologies/tyk-pump v1.8.0-rc4 - github.com/buger/jsonparser v1.1.1 -) - -require ( - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/Shopify/sarama v1.29.1 // indirect - github.com/TykTechnologies/gojsonschema v0.0.0-20170222154038-dcb3e4bb7990 // indirect - github.com/TykTechnologies/graphql-go-tools v1.6.2-0.20230412102031-738c1d218c03 // indirect - github.com/TykTechnologies/murmur3 v0.0.0-20230310161213-aad17efd5632 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/clbanning/mxj v1.8.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/eapache/go-resiliency v1.2.0 // indirect - github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect - github.com/eapache/queue v1.1.0 // indirect - github.com/eclipse/paho.mqtt.golang v1.2.0 // indirect - github.com/fatih/structs v1.1.0 // indirect - github.com/go-redis/redis/v8 v8.11.5 // indirect - github.com/gofrs/uuid v3.3.0+incompatible // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/jcmturner/aescts/v2 v2.0.0 // indirect - github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect - github.com/jcmturner/gofork v1.0.0 // indirect - github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect - github.com/jcmturner/rpc/v2 v2.0.3 // indirect - github.com/jensneuse/abstractlogger v0.0.4 // indirect - github.com/jensneuse/byte-template v0.0.0-20200214152254-4f3cf06e5c68 // indirect - github.com/jensneuse/pipeline v0.0.0-20200117120358-9fb4de085cd6 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.2 // indirect - github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.15.9 // indirect - github.com/lonelycode/go-uuid v0.0.0-20141202165402-ed3ca8a15a93 // indirect - github.com/lonelycode/osin v0.0.0-20160423095202-da239c9dacb6 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30 // indirect - github.com/nats-io/nkeys v0.3.0 // indirect - github.com/nats-io/nuid v1.0.1 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/oschwald/maxminddb-golang v1.5.0 // indirect - github.com/pierrec/lz4 v2.6.0+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmylund/go-cache v2.1.0+incompatible // indirect - github.com/qri-io/jsonpointer v0.1.1 // indirect - github.com/qri-io/jsonschema v0.2.1 // indirect - github.com/r3labs/sse/v2 v2.8.1 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect - github.com/tidwall/gjson v1.11.0 // indirect - github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect - github.com/tidwall/sjson v1.0.4 // indirect - github.com/uber/jaeger-client-go v2.30.1-0.20220110192849-8d8e8fcfd04d+incompatible // indirect - github.com/uber/jaeger-lib v2.4.2-0.20210604143007-135cf5605a6d+incompatible // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.18.1 // indirect - golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 // indirect - golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect - gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/gorm v1.21.10 // indirect - nhooyr.io/websocket v1.8.7 // indirect -) diff --git a/ci/images/plugin-compiler/data/basic-plugin/go.sum b/ci/images/plugin-compiler/data/basic-plugin/go.sum deleted file mode 100644 index bf464424c83..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/go.sum +++ /dev/null @@ -1,1236 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/99designs/gqlgen v0.17.20 h1:O7WzccIhKB1dm+7g6dhQcULINftfiLSBg2l/mwbpJMw= -github.com/99designs/gqlgen v0.17.20/go.mod h1:Mja2HI23kWT1VRH09hvWshFgOzKswpO20o4ScpJIES4= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DataDog/datadog-go v4.7.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= -github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Jeffail/tunny v0.1.4/go.mod h1:P8xAx4XQl0xsuhjX1DtfaMDCSuavzdb2rwbd0lk+fvo= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.29.1 h1:wBAacXbYVLmWieEA/0X/JagDdCZ8NVFOfS6l6+2u5S0= -github.com/Shopify/sarama v1.29.1/go.mod h1:mdtqvCSg8JOxk8PmpTNGyo6wzd4BMm4QXSfDnTXmgkE= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/TykTechnologies/again v0.0.0-20190805133618-6ad301e7eaed/go.mod h1:OUrgdjjCoYX2GZY9Vathb4ExCO9WuPtU1piuOpNw19Q= -github.com/TykTechnologies/circuitbreaker v2.2.2+incompatible/go.mod h1:f2+J36wN08/zLudMnO+QaqaBhTdQuIqemtaeEQbhMEM= -github.com/TykTechnologies/drl v0.0.0-20221208085827-9bc9b4338f26/go.mod h1:F3Ff6Ih4t1i/etqNJHI2K3jverRhNl759J/ra95/3Hk= -github.com/TykTechnologies/goautosocket v0.0.0-20190430121222-97bfa5e7e481/go.mod h1:CtF8OunV123VfKa8Z9kKcIPHgcd67hSAwFMLlS7FvS4= -github.com/TykTechnologies/gojsonschema v0.0.0-20170222154038-dcb3e4bb7990 h1:CJRTgg13M3vJG9S7k7kpnvDRMGMywm5OsN6eUE8VwJE= -github.com/TykTechnologies/gojsonschema v0.0.0-20170222154038-dcb3e4bb7990/go.mod h1:SQT0NBrY4/pMikBgwFIrWCjcHBxg015Y8is0kAnMtug= -github.com/TykTechnologies/gorpc v0.0.0-20210624160652-fe65bda0ccb9/go.mod h1:v6v7Mlj08+EmEcXOfpuTxGt2qYU9yhqqtv4QF9Wf50E= -github.com/TykTechnologies/goverify v0.0.0-20220808203004-1486f89e7708/go.mod h1:mkS8jKcz8otdfEXhJs1QQ/DKoIY1NFFsRPKS0RwQENI= -github.com/TykTechnologies/graphql-go-tools v1.6.2-0.20230320143102-7a16078ce517/go.mod h1:ZiFZcrue3+n2mHH+KLHRipbYVULkgy3Myko5S7IIs74= -github.com/TykTechnologies/graphql-go-tools v1.6.2-0.20230412102031-738c1d218c03 h1:1vzCUTJfmx/peGGtmr5bQZBEq8Q/7JdVSawPMUFdd6o= -github.com/TykTechnologies/graphql-go-tools v1.6.2-0.20230412102031-738c1d218c03/go.mod h1:Fjaf4vD/lBTjBdwG+eCd+VhQzKNZBRw+9nygH4IUHlA= -github.com/TykTechnologies/leakybucket v0.0.0-20170301023702-71692c943e3c/go.mod h1:GnHUbsQx+ysI10osPhUdTmsxcE7ef64cVp38Fdyd7e0= -github.com/TykTechnologies/murmur3 v0.0.0-20230310161213-aad17efd5632 h1:T5NWziFusj8au5nxAqMMh/bZyX9CAyYnBkaMSsfH6BA= -github.com/TykTechnologies/murmur3 v0.0.0-20230310161213-aad17efd5632/go.mod h1:UsPYgOFBpNzDXLEti7MKOwHLpVSqdzuNGkVFPspQmnQ= -github.com/TykTechnologies/openid2go v0.1.2/go.mod h1:gYfkqeWa+lY3Xz/Z2xYtIzmYXynlgKZaBIbPCqdcdMA= -github.com/TykTechnologies/tyk v1.9.2-0.20230419071249-a0633247127a h1:gKNUX+ML4W5CHpYDSI9qrQEJticNZ8uCENZWZ+9gbiM= -github.com/TykTechnologies/tyk v1.9.2-0.20230419071249-a0633247127a/go.mod h1:tRZxXuREGqWUpLyuLLxfFqXIdLQkK6jLSxAenVj0F/o= -github.com/TykTechnologies/tyk-pump v1.8.0-rc4 h1:odhM/skFNYWBdSL+atx49f6/PleNRq6l4E9SyeDfmTg= -github.com/TykTechnologies/tyk-pump v1.8.0-rc4/go.mod h1:dTxcW0leM1oHhMJOxM784iTuWe+D2SnffAEhmHPZOug= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= -github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asyncapi/converter-go v0.0.0-20190802111537-d8459b2bd403/go.mod h1:mpJYWYy+USNiLENQxiyGgRc3qtFPxYSWdSd/eS+R6bo= -github.com/asyncapi/parser-go v0.4.2/go.mod h1:5iAT+irO9xKeBDnIhqT0ev8QJH1dHq4i2oU/UBhhwB8= -github.com/asyncapi/spec-json-schemas/v2 v2.14.0/go.mod h1:5lFCFtRGfI3WVOla4slifjgPs9x79FY0fqZjgNL495c= -github.com/aws/aws-sdk-go v1.29.11/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= -github.com/aws/aws-sdk-go v1.40.32/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go-v2 v1.10.0/go.mod h1:U/EyyVvKtzmFeQQcca7eBotKdlpcP2zzU6bXBYcf7CE= -github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= -github.com/aws/aws-sdk-go-v2 v1.16.14/go.mod h1:s/G+UV29dECbF5rf+RNj1xhlmvoNurGSr+McVSRj59w= -github.com/aws/aws-sdk-go-v2/config v1.9.0/go.mod h1:qhK5NNSgo9/nOSMu3HyE60WHXZTWTHTgd5qtIF44vOQ= -github.com/aws/aws-sdk-go-v2/credentials v1.5.0/go.mod h1:kvqTkpzQmzri9PbsiTY+LvwFzM0gY19emlAWwBOJMb0= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.7.0/go.mod h1:KqEkRkxm/+1Pd/rENRNbQpfblDBYeg5HDSqjB6ks8hA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.2.5/go.mod h1:6ZBTuDmvpCOD4Sf1i2/I3PgftlEcDGgvi8ocq64oQEg= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.3.3/go.mod h1:zOyLMYyg60yyZpOCniAUuibWVqTU4TuLmMa/Wh4P+HA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.4.0/go.mod h1:X5/JuOxPLU/ogICgDTtnpfaQzdQJO0yKDcpoxWLLJ8Y= -github.com/aws/aws-sdk-go-v2/service/sso v1.5.0/go.mod h1:GsqaJOJeOfeYD88/2vHWKXegvDRofDqWwC5i48A2kgs= -github.com/aws/aws-sdk-go-v2/service/sts v1.8.0/go.mod h1:dOlm91B439le5y1vtPCk5yJtbx3RdT3hRGYRY8TYKvQ= -github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.9.0/go.mod h1:VN4yDJwgYOO6AzHPE8+QeBwK6wUMOFkSCogZFWifdVc= -github.com/aws/smithy-go v1.8.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.13.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/beeker1121/goque v0.0.0-20170321141813-4044bc29b280/go.mod h1:L6dOWBhDOnxUVQsb0wkLve0VCnt2xJW/MI8pdRX4ANw= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= -github.com/cenk/backoff v2.2.1+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20190905060710-a5e0173ced67/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= -github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q= -github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evalphobia/logrus_sentry v0.8.2/go.mod h1:pKcp+vriitUqu9KiWj/VRFbRfFNUwz95/UkgG8a6MNc= -github.com/evanphx/json-patch/v5 v5.1.0 h1:B0aXl1o/1cP8NbviYiBMkcHBtUjIJ1/Ccg6b+SwCLQg= -github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gemnasium/logrus-graylog-hook v2.0.7+incompatible/go.mod h1:85jwR23cg8rapnMQj96B9pX4XzmkXMNAPVfnnUNP8Dk= -github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getkin/kin-openapi v0.115.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-redis/redis/v8 v8.3.1/go.mod h1:a2xkpBM7NJUN5V5kiF46X5Ltx4WeXJ9757X/ScKUBdE= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-zookeeper/zk v1.0.2 h1:4mx0EYENAdX/B/rbunjlt5+4RTA/a9SMHBRuSKdGxPM= -github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs= -github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gocraft/health v0.0.0-20170925182251-8675af27fef0/go.mod h1:rWibcVfwbUxi/QXW84U7vNTcIcZFd6miwbt8ritxh/Y= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gotestyourself/gotestyourself v1.4.0/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.2.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= -github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= -github.com/influxdata/influxdb-client-go/v2 v2.6.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU= -github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.7.0/go.mod h1:sF/lPpNEMEOp+IYhyQGdAvrG20gWf6A1tKlr0v7JMeA= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.5/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.5.0/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.9.0/go.mod h1:MNGWmViCgqbZck9ujOOBN63gK9XVGILXWCvKLGKmnms= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= -github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= -github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= -github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= -github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= -github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= -github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= -github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jehiah/go-strftime v0.0.0-20151206194810-2efbe75097a5/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= -github.com/jensneuse/abstractlogger v0.0.4 h1:sa4EH8fhWk3zlTDbSncaWKfwxYM8tYSlQ054ETLyyQY= -github.com/jensneuse/abstractlogger v0.0.4/go.mod h1:6WuamOHuykJk8zED/R0LNiLhWR6C7FIAo43ocUEB3mo= -github.com/jensneuse/byte-template v0.0.0-20200214152254-4f3cf06e5c68 h1:E80wOd3IFQcoBxLkAUpUQ3BoGrZ4DxhQdP21+HH1s6A= -github.com/jensneuse/byte-template v0.0.0-20200214152254-4f3cf06e5c68/go.mod h1:0D5r/VSW6D/o65rKLL9xk7sZxL2+oku2HvFPYeIMFr4= -github.com/jensneuse/diffview v1.0.0 h1:4b6FQJ7y3295JUHU3tRko6euyEboL825ZsXeZZM47Z4= -github.com/jensneuse/diffview v1.0.0/go.mod h1:i6IacuD8LnEaPuiyzMHA+Wfz5mAuycMOf3R/orUY9y4= -github.com/jensneuse/pipeline v0.0.0-20200117120358-9fb4de085cd6 h1:y8hvuqbuVGFNpEos+vB5I5X+QxWm0uyTk+5oeOinMjY= -github.com/jensneuse/pipeline v0.0.0-20200117120358-9fb4de085cd6/go.mod h1:UsfzaMt+keVOxa007GcCJMFeTHr6voRfBGMQEW7DkdM= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= -github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lintianzhi/graylogd v0.0.0-20180503131252-dc68342f04dc/go.mod h1:WTHfLzkGmTEe+nyJqdZhFbAWUkyI30IVS9ytgHDJj0I= -github.com/logrusorgru/aurora/v3 v3.0.0 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4= -github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= -github.com/logzio/logzio-go v0.0.0-20200316143903-ac8fc0e2910e/go.mod h1:OBprCVuGvtyYcaCmYjE32bF12d5AAHeXS5xI0QbIXMI= -github.com/lonelycode/go-uuid v0.0.0-20141202165402-ed3ca8a15a93 h1:WcaWCUFwpiRpIjcM7u27kuy2p5zPLC1KRxB3/bJ7XsI= -github.com/lonelycode/go-uuid v0.0.0-20141202165402-ed3ca8a15a93/go.mod h1:ZjpSGzPgHSthaPv5L+rBEMIwrr5Uto0pKPwHmCHRkUM= -github.com/lonelycode/mgohacks v0.0.0-20150820024025-f9c291f7e57e/go.mod h1:xVJqf7VdD7Xfgmi9XY63aOYtrYClQOtwHX2FEOgtCKM= -github.com/lonelycode/osin v0.0.0-20160423095202-da239c9dacb6 h1:G2UYdR7/shMh7NMp2ETozj6zlqU5M8b0VqRbdxTXciU= -github.com/lonelycode/osin v0.0.0-20160423095202-da239c9dacb6/go.mod h1:x4kc0i0iLfRkNWchVMcLjy+Txcz3XqNbr8iRUGFduLQ= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mavricknz/asn1-ber v0.0.0-20151103223136-b9df1c2f4213/go.mod h1:v/ZufymxjcI3pnNmQIUQQKxnHLTblrjZ4MNLs5DrZ1o= -github.com/mavricknz/ldap v0.0.0-20160227184754-f5a958005e43/go.mod h1:z76yvVwVulPd8FyifHe8UEHeud6XXaSan0ibi2sDy6w= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= -github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/moesif/moesifapi-go v1.0.6/go.mod h1:wRGgVy0QeiCgnjFEiD13HD2Aa7reI8nZXtCnddNnZGs= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU= -github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= -github.com/nats-io/jwt/v2 v2.0.2/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= -github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI= -github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= -github.com/nats-io/nats-server/v2 v2.3.2/go.mod h1:dUf7Cm5z5LbciFVwWx54owyCKm8x4/hL6p7rrljhLFY= -github.com/nats-io/nats-server/v2 v2.3.4 h1:WcNa6HDFX8gjZPHb8CJ9wxRHEjJSlhWUb/MKb6/mlUY= -github.com/nats-io/nats-server/v2 v2.3.4/go.mod h1:3mtbaN5GkCo/Z5T3nNj0I0/W1fPkKzLiDC6jjWJKp98= -github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30 h1:9GqilBhZaR3xYis0JgMlJjNw933WIobdjKhilXm+Vls= -github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= -github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/newrelic/go-agent v2.13.0+incompatible/go.mod h1:a8Fv1b/fYhFSReoTU6HDkTYIMZeSVNffmoS726Y0LzQ= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nsf/jsondiff v0.0.0-20210303162244-6ea32392771e h1:S+/ptYdZtpK/MDstwCyt+ZHdXEpz86RJZ5gyZU4txJY= -github.com/nsf/jsondiff v0.0.0-20210303162244-6ea32392771e/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olivere/elastic v6.2.31+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= -github.com/olivere/elastic/v7 v7.0.12/go.mod h1:14rWX28Pnh3qCKYRVnSGXWLf9MbLonYS/4FDCY3LAPo= -github.com/olivere/elastic/v7 v7.0.28/go.mod h1:DzHQoqd6YqSuvF1lk/fR4cW4FNUNzSD5/F5MBm3GRMo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= -github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw= -github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= -github.com/oschwald/maxminddb-golang v1.5.0 h1:rmyoIV6z2/s9TCJedUuDiKht2RN12LWJ1L7iRGtWY64= -github.com/oschwald/maxminddb-golang v1.5.0/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= -github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg= -github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A= -github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pires/go-proxyproto v0.0.0-20190615163442-2c19fd512994/go.mod h1:6/gX3+E/IYGa0wMORlSMla999awQFdbaeQCHjSMKIzY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmylund/go-cache v2.1.0+incompatible h1:n+7K51jLz6a3sCvff3BppuCAkixuDHuJ/C57Vw/XjTE= -github.com/pmylund/go-cache v2.1.0+incompatible/go.mod h1:hmz95dGvINpbRZGsqPcd7B5xXY5+EKb5PpGhQY3NTHk= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA= -github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= -github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0= -github.com/qri-io/jsonschema v0.2.1/go.mod h1:g7DPkiOsK1xv6T/Ao5scXRkd+yTFygcANPBaaqW+VrI= -github.com/quipo/statsd v0.0.0-20160923160612-75b7afedf0d2/go.mod h1:1COUodqytMiv/GkAVUGhc0CA6e8xak5U4551TY7iEe0= -github.com/r3labs/sse/v2 v2.8.1 h1:lZH+W4XOLIq88U5MIHOsLec7+R62uhz3bIi2yn0Sg8o= -github.com/r3labs/sse/v2 v2.8.1/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/resurfaceio/logger-go/v3 v3.2.1/go.mod h1:YPcxFUcloW37F1WQA9MUcGWu2JzlvBxlCfFF5+T3GO8= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/robertkowalski/graylog-golang v0.0.0-20151121031040-e5295cfa2827/go.mod h1:jONcYFk83vUF1lv0aERAwaFtDM9wUW4BMGmlnpLJyZY= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sebdah/goldie v0.0.0-20180424091453-8784dd1ab561 h1:IY+sDBJR/wRtsxq+626xJnt4Tw7/ROA9cDIR8MMhWyg= -github.com/sebdah/goldie v0.0.0-20180424091453-8784dd1ab561/go.mod h1:lvjGftC8oe7XPtyrOidaMi0rp5B9+XY/ZRUynGnuaxQ= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/segmentio/analytics-go v0.0.0-20160711225931-bdb0aeca8a99/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48= -github.com/segmentio/backo-go v0.0.0-20160424052352-204274ad699c/go.mod h1:kJ9mm9YmoWSkk+oQ+5Cj8DEoRCX2JT6As4kEtIIOp1M= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.3.6/go.mod h1:8rEphJEczp+yDE/R5vwmaqZgF1wllrl4ioQcNKB8wVA= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil v3.20.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/gunit v1.1.3/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ= -github.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/square/go-jose v2.4.1+incompatible/go.mod h1:7MxpAF/1WTVUu8Am+T5kNy+t0902CaLWM4Z745MkOa8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4= -github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.0.4 h1:UcdIRXff12Lpnu3OLtZvnc03g4vH2suXDXhBwBqmzYg= -github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/uber/jaeger-client-go v2.30.1-0.20220110192849-8d8e8fcfd04d+incompatible h1:Nriupf3YYKvA5oxiej8Bb+ao/oanuw9lvahjIQc4nEc= -github.com/uber/jaeger-client-go v2.30.1-0.20220110192849-8d8e8fcfd04d+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.4.2-0.20210604143007-135cf5605a6d+incompatible h1:73eb49SfAfRZEhxIKR0tz5MUMu2zjJxJUZlFCHInV34= -github.com/uber/jaeger-lib v2.4.2-0.20210604143007-135cf5605a6d+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.43.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/vektah/gqlparser/v2 v2.5.1 h1:ZGu+bquAY23jsxDRcYpWjttRZrUz07LbiY77gUOHcr4= -github.com/vektah/gqlparser/v2 v2.5.1/go.mod h1:mPgqFBu/woKTVYWyNk8cO3kh4S/f4aRFZrvOnp3hmCs= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/scram v1.0.3/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 h1:NUzdAbFtCJSXU20AOXgeqaUwg8Ypg4MPYmL+d+rsB5c= -golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo= -golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc/examples v0.0.0-20220317213542-f95b001a48df/go.mod h1:wKDg0brwMZpaizQ1i7IzYcJjH1TmbJudYdnQC9+J+LE= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= -gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= -gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/olivere/elastic.v3 v3.0.56/go.mod h1:yDEuSnrM51Pc8dM5ov7U8aI/ToR3PG0llA8aRv2qmw0= -gopkg.in/olivere/elastic.v5 v5.0.85/go.mod h1:M3WNlsF+WhYn7api4D87NIflwTV/c0iVs8cqfWhK+68= -gopkg.in/olivere/elastic.v6 v6.2.31/go.mod h1:2cTT8Z+/LcArSWpCgvZqBgt3VOqXiy7v00w12Lz8bd4= -gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= -gopkg.in/xmlpath.v2 v2.0.0-20150820204837-860cbeca3ebc/go.mod h1:N8UOSI6/c2yOpa/XDz3KVUiegocTziPiqNkeNTMiG1k= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI= -gorm.io/driver/postgres v1.0.5/go.mod h1:qrD92UurYzNctBMVCJ8C3VQEjffEuphycXtxOudXNCA= -gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c= -gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.10 h1:kBGiBsaqOQ+8f6S2U6mvGFz6aWWyCeIiuaFcaBozp4M= -gorm.io/gorm v1.21.10/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/ci/images/plugin-compiler/data/build.sh b/ci/images/plugin-compiler/data/build.sh index 0015b24f2e5..d2bed2b592d 100755 --- a/ci/images/plugin-compiler/data/build.sh +++ b/ci/images/plugin-compiler/data/build.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -GATEWAY_VERSION=$(perl -n -e'/v(\d+).(\d+).(\d+)/'' && print "v$1\.$2\.$3"' $TYK_GW_PATH/gateway/version.go) +GATEWAY_VERSION=$(echo $GITHUB_TAG | perl -n -e'/v(\d+).(\d+).(\d+)/'' && print "v$1\.$2\.$3"') # Plugin compiler arguments: # @@ -25,8 +25,10 @@ GOOS=${3:-$(go env GOOS)} GOARCH=${4:-$(go env GOARCH)} # Some defaults that can be overriden with env +WORKSPACE_ROOT=$(dirname $TYK_GW_PATH) + PLUGIN_SOURCE_PATH=${PLUGIN_SOURCE_PATH:-"/plugin-source"} -PLUGIN_BUILD_PATH=${PLUGIN_BUILD_PATH:-"/opt/plugin_${plugin_name%.*}$plugin_id"} +PLUGIN_BUILD_PATH=${PLUGIN_BUILD_PATH:-"${WORKSPACE_ROOT}/plugin_${plugin_name%.*}$plugin_id"} function usage() { cat </dev/null 2>&1; then if [ ! -f /lib/systemd/system/tyk-gateway.service ]; then diff --git a/ci/terraform/outputs.tf b/ci/terraform/outputs.tf index f2b5a39db0e..59b1deffe0c 100644 --- a/ci/terraform/outputs.tf +++ b/ci/terraform/outputs.tf @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Mon Jun 5 16:49:38 UTC 2023 +# Generated on: Wed Jun 7 07:45:11 UTC 2023 From 047840170a994c59a7899517365636cb483a66a5 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 15 Jun 2023 13:33:50 +0300 Subject: [PATCH 03/33] Merging to release-4-lts: [TT-2301] Create scope local variables for director for all required vars (#5088) [TT-2301] Create scope local variables for director for all required vars (#5088) ## Description Fix logger according to scope; Add scope local variables for director to use, avoiding unexpected behaviour/races. ## Related Issue Fixes #2980 #2952 https://tyktech.atlassian.net/browse/TT-2301 ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why Co-authored-by: Tit Petric --- gateway/reverse_proxy.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/gateway/reverse_proxy.go b/gateway/reverse_proxy.go index 40a8e5431cb..a4bfc27b8e7 100644 --- a/gateway/reverse_proxy.go +++ b/gateway/reverse_proxy.go @@ -232,27 +232,38 @@ func (gw *Gateway) TykNewSingleHostReverseProxy(target *url.URL, spec *APISpec, } } + if logger == nil { + logger = logrus.NewEntry(log) + } + + logger = logger.WithField("mw", "ReverseProxy") + targetQuery := target.RawQuery director := func(req *http.Request) { + logger := logger + spec := spec + target := target + gw := gw + hostList := spec.Proxy.StructuredTargetList switch { case spec.Proxy.ServiceDiscovery.UseDiscoveryService: var err error hostList, err = urlFromService(spec) if err != nil { - log.Error("[PROXY] [SERVICE DISCOVERY] Failed target lookup: ", err) + logger.Error("[PROXY] [SERVICE DISCOVERY] Failed target lookup: ", err) break } fallthrough // implies load balancing, with replaced host list case spec.Proxy.EnableLoadBalancing: host, err := gw.nextTarget(hostList, spec) if err != nil { - log.Error("[PROXY] [LOAD BALANCING] ", err) + logger.Error("[PROXY] [LOAD BALANCING] ", err) host = allHostsDownURL } lbRemote, err := url.Parse(host) if err != nil { - log.Error("[PROXY] [LOAD BALANCING] Couldn't parse target URL:", err) + logger.Error("[PROXY] [LOAD BALANCING] Couldn't parse target URL:", err) } else { // Only replace target if everything is OK target = lbRemote @@ -263,10 +274,10 @@ func (gw *Gateway) TykNewSingleHostReverseProxy(target *url.URL, spec *APISpec, targetToUse := target if spec.URLRewriteEnabled && req.Context().Value(ctx.RetainHost) == true { - log.Debug("Detected host rewrite, overriding target") + logger.Debug("Detected host rewrite, overriding target") tmpTarget, err := url.Parse(req.URL.String()) if err != nil { - log.Error("Failed to parse URL! Err: ", err) + logger.Error("Failed to parse URL! Err: ", err) } else { // Specifically override with a URL rewrite targetToUse = tmpTarget @@ -321,12 +332,6 @@ func (gw *Gateway) TykNewSingleHostReverseProxy(target *url.URL, spec *APISpec, } } - if logger == nil { - logger = logrus.NewEntry(log) - } - - logger = logger.WithField("mw", "ReverseProxy") - proxy := &ReverseProxy{ Director: director, TykAPISpec: spec, From 6b38e182be6796605a34e1a0b1deb6dd25427136 Mon Sep 17 00:00:00 2001 From: Tyk-ITS Account <92926870+Tyk-ITS@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:17:45 +0100 Subject: [PATCH 04/33] [CI] Sync automation: Syncing commits from master Picking CI changes from the commit 92404e6b44dddb92d4ca66c03cf5b0f1368e2431 --- .github/dependabot.yml | 2 +- .github/workflows/del-env.yml | 2 +- .github/workflows/release.yml | 2 +- ci/Dockerfile.std | 2 +- ci/aws/byol.pkr.hcl | 2 +- ci/goreleaser/goreleaser.yml | 2 +- ci/images/plugin-compiler/Dockerfile | 7 +++++-- ci/images/plugin-compiler/data/build.sh | 9 ++++++++- ci/install/before_install.sh | 2 +- ci/install/post_install.sh | 2 +- ci/install/post_remove.sh | 2 +- ci/install/post_trans.sh | 2 +- ci/terraform/outputs.tf | 2 +- 13 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2a39ef51738..1ebf1d33c62 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 version: 2 updates: diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml index 9e2d3aa0e04..46e0dd819b8 100644 --- a/.github/workflows/del-env.yml +++ b/.github/workflows/del-env.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 name: Retiring dev env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6b2aaeb2e8..5fa2471973d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 # Distribution channels covered by this workflow diff --git a/ci/Dockerfile.std b/ci/Dockerfile.std index 8c4ee847841..04a28972b0e 100644 --- a/ci/Dockerfile.std +++ b/ci/Dockerfile.std @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 FROM debian:bullseye-slim ARG TARGETARCH diff --git a/ci/aws/byol.pkr.hcl b/ci/aws/byol.pkr.hcl index fe7ede36197..bd9fb1f27ac 100644 --- a/ci/aws/byol.pkr.hcl +++ b/ci/aws/byol.pkr.hcl @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 packer { required_plugins { diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index ad9aa49c5e3..5adea446c9a 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -1,5 +1,5 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 # Check the documentation at http://goreleaser.com # This project needs CGO_ENABLED=1 and the cross-compiler toolchains for diff --git a/ci/images/plugin-compiler/Dockerfile b/ci/images/plugin-compiler/Dockerfile index 7fa40e08b6a..a62fed80ac4 100644 --- a/ci/images/plugin-compiler/Dockerfile +++ b/ci/images/plugin-compiler/Dockerfile @@ -1,5 +1,6 @@ -ARG GOLANG_CROSS -FROM tykio/golang-cross:${GOLANG_CROSS} +ARG BASE_IMAGE +FROM ${BASE_IMAGE} + LABEL description="Image for plugin development" ENV TYK_GW_PATH=/go/src/github.com/TykTechnologies/tyk @@ -22,6 +23,8 @@ ADD . $TYK_GW_PATH ARG GITHUB_SHA ARG GITHUB_TAG +ARG BASE_IMAGE +ENV BASE_IMAGE ${BASE_IMAGE} ENV GITHUB_SHA ${GITHUB_SHA} ENV GITHUB_TAG ${GITHUB_TAG} diff --git a/ci/images/plugin-compiler/data/build.sh b/ci/images/plugin-compiler/data/build.sh index d2bed2b592d..0d8b919bbc0 100755 --- a/ci/images/plugin-compiler/data/build.sh +++ b/ci/images/plugin-compiler/data/build.sh @@ -44,6 +44,12 @@ if [ -z "$plugin_name" ]; then exit 1 fi +CC=$(go env CC) + +if [[ $BASE_IMAGE == *"golang-cross"* ]] && [[ $GOARCH == "arm64" ]] && [[ $GOOS == "linux" ]] ; then + CC=aarch64-linux-gnu-gcc +fi + # if arch and os present then update the name of file with those params if [[ $GOOS != "" ]] && [[ $GOARCH != "" ]]; then plugin_name="${plugin_name%.*}_${GATEWAY_VERSION}_${GOOS}_${GOARCH}.so" @@ -73,9 +79,10 @@ set +x echo "PLUGIN_BUILD_PATH: ${PLUGIN_BUILD_PATH}" echo "PLUGIN_SOURCE_PATH: ${PLUGIN_SOURCE_PATH}" +echo "CC: ${CC}" echo "plugin_name: ${plugin_name}" set -x -CGO_ENABLED=1 GOOS=$GOOS GOARCH=$GOARCH go build -buildmode=plugin -trimpath -o $plugin_name +CC=$CC CGO_ENABLED=1 GOOS=$GOOS GOARCH=$GOARCH go build -buildmode=plugin -trimpath -o $plugin_name mv $plugin_name $PLUGIN_SOURCE_PATH rm -f $WORKSPACE_ROOT/go.work diff --git a/ci/install/before_install.sh b/ci/install/before_install.sh index 68a5a5ab2ce..f552dee5237 100755 --- a/ci/install/before_install.sh +++ b/ci/install/before_install.sh @@ -1,7 +1,7 @@ #!/bin/bash # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 echo "Creating user and group..." GROUPNAME="tyk" diff --git a/ci/install/post_install.sh b/ci/install/post_install.sh index 69b606f8116..ed172c8fda1 100755 --- a/ci/install/post_install.sh +++ b/ci/install/post_install.sh @@ -2,7 +2,7 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 # If "True" the install directory ownership will be changed to "tyk:tyk" change_ownership="False" diff --git a/ci/install/post_remove.sh b/ci/install/post_remove.sh index 13c8219561f..22a683e56d9 100755 --- a/ci/install/post_remove.sh +++ b/ci/install/post_remove.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 cleanRemove() { diff --git a/ci/install/post_trans.sh b/ci/install/post_trans.sh index 417f730121d..2d5f20a6ae5 100644 --- a/ci/install/post_trans.sh +++ b/ci/install/post_trans.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 if command -V systemctl >/dev/null 2>&1; then if [ ! -f /lib/systemd/system/tyk-gateway.service ]; then diff --git a/ci/terraform/outputs.tf b/ci/terraform/outputs.tf index 59b1deffe0c..81edc532f24 100644 --- a/ci/terraform/outputs.tf +++ b/ci/terraform/outputs.tf @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Wed Jun 7 07:45:11 UTC 2023 +# Generated on: Thu Jun 15 12:14:49 UTC 2023 From 681194ccdb1243bf090d49cbdec5a4c987474d1f Mon Sep 17 00:00:00 2001 From: Tyk-ITS Account <92926870+Tyk-ITS@users.noreply.github.com> Date: Fri, 16 Jun 2023 09:43:00 +0100 Subject: [PATCH 05/33] [CI] Sync automation: Syncing commits from master Picking CI changes from the commit 5dc52ef6d204c867cd7031b06f31e8d0f263c6d0 --- .github/dependabot.yml | 2 +- .github/workflows/api-tests.yml | 4 ++++ .github/workflows/del-env.yml | 2 +- .github/workflows/release.yml | 2 +- ci/Dockerfile.std | 2 +- ci/aws/byol.pkr.hcl | 2 +- ci/goreleaser/goreleaser.yml | 2 +- ci/install/before_install.sh | 2 +- ci/install/post_install.sh | 2 +- ci/install/post_remove.sh | 2 +- ci/install/post_trans.sh | 2 +- ci/terraform/outputs.tf | 2 +- 12 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1ebf1d33c62..6a900ac3c47 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 version: 2 updates: diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index d9b6d60d2d2..6b50254bf72 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -176,3 +176,7 @@ jobs: CLIENT_ID: ${{secrets.XRAY_CLIENT_ID}} CLIENT_SECRET: ${{secrets.XRAY_CLIENT_SECRET}} BRANCH: ${{ github.ref }} + + - name: Getting gateway logs on failure + if: ${{ failure() }} + run: docker logs tyk-gateway diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml index 46e0dd819b8..1e26109d3fb 100644 --- a/.github/workflows/del-env.yml +++ b/.github/workflows/del-env.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 name: Retiring dev env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5fa2471973d..34b413dccc0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 # Distribution channels covered by this workflow diff --git a/ci/Dockerfile.std b/ci/Dockerfile.std index 04a28972b0e..f1518f0864d 100644 --- a/ci/Dockerfile.std +++ b/ci/Dockerfile.std @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 FROM debian:bullseye-slim ARG TARGETARCH diff --git a/ci/aws/byol.pkr.hcl b/ci/aws/byol.pkr.hcl index bd9fb1f27ac..3debf4f69b2 100644 --- a/ci/aws/byol.pkr.hcl +++ b/ci/aws/byol.pkr.hcl @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 packer { required_plugins { diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index 5adea446c9a..fca30eab1f0 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -1,5 +1,5 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 # Check the documentation at http://goreleaser.com # This project needs CGO_ENABLED=1 and the cross-compiler toolchains for diff --git a/ci/install/before_install.sh b/ci/install/before_install.sh index f552dee5237..3045b5d76c6 100755 --- a/ci/install/before_install.sh +++ b/ci/install/before_install.sh @@ -1,7 +1,7 @@ #!/bin/bash # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 echo "Creating user and group..." GROUPNAME="tyk" diff --git a/ci/install/post_install.sh b/ci/install/post_install.sh index ed172c8fda1..5d3c9006248 100755 --- a/ci/install/post_install.sh +++ b/ci/install/post_install.sh @@ -2,7 +2,7 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 # If "True" the install directory ownership will be changed to "tyk:tyk" change_ownership="False" diff --git a/ci/install/post_remove.sh b/ci/install/post_remove.sh index 22a683e56d9..10dfab0d4af 100755 --- a/ci/install/post_remove.sh +++ b/ci/install/post_remove.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 cleanRemove() { diff --git a/ci/install/post_trans.sh b/ci/install/post_trans.sh index 2d5f20a6ae5..574cfd07013 100644 --- a/ci/install/post_trans.sh +++ b/ci/install/post_trans.sh @@ -1,7 +1,7 @@ #!/bin/sh # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 if command -V systemctl >/dev/null 2>&1; then if [ ! -f /lib/systemd/system/tyk-gateway.service ]; then diff --git a/ci/terraform/outputs.tf b/ci/terraform/outputs.tf index 81edc532f24..4f9e2ad1e92 100644 --- a/ci/terraform/outputs.tf +++ b/ci/terraform/outputs.tf @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Thu Jun 15 12:14:49 UTC 2023 +# Generated on: Fri Jun 16 08:40:35 UTC 2023 From a3c957227320eeb4ac3b9731c2ba7b0893b70231 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 27 Jun 2023 11:25:50 +0300 Subject: [PATCH 06/33] Merging to release-4-lts: [TT-9196] fix dashboard client timeout (#5176) [TT-9196] fix dashboard client timeout (#5176) Dashboard client on the gateway side has a hardcoded 30 seconds and times out when dealing with larger amounts of APIs and Policies. Instead of the 30 seconds we can parametrize that value and allow the customer to determine the amount they are comfortable with. ## Description ## Related Issue https://tyktech.atlassian.net/browse/TT-9196 ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --- cli/linter/schema.json | 3 +++ config/config.go | 3 +++ gateway/dashboard_register.go | 13 +++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cli/linter/schema.json b/cli/linter/schema.json index b21db87facc..9f34d515c34 100644 --- a/cli/linter/schema.json +++ b/cli/linter/schema.json @@ -303,6 +303,9 @@ "connection_string": { "type": "string" }, + "connection_timeout": { + "type": "integer" + }, "node_is_segmented": { "type": "boolean" }, diff --git a/config/config.go b/config/config.go index 5d0b86d45fa..a124ff03afa 100644 --- a/config/config.go +++ b/config/config.go @@ -89,6 +89,9 @@ type DBAppConfOptionsConfig struct { // Set the URL to your Dashboard instance (or a load balanced instance). The URL needs to be formatted as: `http://dashboard_host:port` ConnectionString string `json:"connection_string"` + // Set the timeout for your Dashboard connection. Defaults to 30 seconds. In seconds. + ConnectionTimeout int `json:"connection_timeout"` + // Set to `true` to enable filtering (sharding) of APIs. NodeIsSegmented bool `json:"node_is_segmented"` diff --git a/gateway/dashboard_register.go b/gateway/dashboard_register.go index 8c2336016c0..bbeae7b9b8f 100644 --- a/gateway/dashboard_register.go +++ b/gateway/dashboard_register.go @@ -60,11 +60,20 @@ var dashClient *http.Client func (gw *Gateway) initialiseClient() *http.Client { if dashClient == nil { + conf := gw.GetConfig() + timeout := conf.DBAppConfOptions.ConnectionTimeout + + // I don't think this is the appropriate place for this. I recommend we look at + // something like https://github.com/mcuadros/go-defaults to normalize all our defaults. + if timeout < 1 { + timeout = 30 + } + dashClient = &http.Client{ - Timeout: 30 * time.Second, + Timeout: time.Duration(timeout) * time.Second, } - if gw.GetConfig().HttpServerOptions.UseSSL { + if conf.HttpServerOptions.UseSSL { // Setup HTTPS client tlsConfig := &tls.Config{ InsecureSkipVerify: gw.GetConfig().HttpServerOptions.SSLInsecureSkipVerify, From 721b452d3f465733b73f0bf374a0d16d66c58c5a Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Jul 2023 13:46:10 +0200 Subject: [PATCH 07/33] [TT-9223] [release-4-lts] sync changes from 4.0.14 (#5265) manual change: - verify github actions - copy over goreleaser - copy over plugin-compiler - copy over ci/Dockerfile.std/slim remaining changes should be automation changes (TD-1998 to track). --------- Co-authored-by: Tit Petric --- .github/workflows/api-tests.yml | 30 +-- .github/workflows/base.yml | 2 +- .github/workflows/ci-tests.yml | 2 +- .github/workflows/del-env.yml | 9 +- .github/workflows/release.yml | 39 +++- ci/Dockerfile.slim | 19 ++ ci/Dockerfile.std | 25 ++- ci/goreleaser/goreleaser-el7.yml | 197 ++++++++++++++++++ ci/goreleaser/goreleaser.yml | 133 +++++++++--- ci/images/plugin-compiler/Dockerfile | 25 +-- .../plugin-compiler/data/basic-plugin/go.mod | 3 - .../data/basic-plugin/test_goplugin.go | 196 ----------------- .../data/basic-plugin/test_goplugin_test.go | 47 ----- ci/images/plugin-compiler/data/build.sh | 85 +++----- ci/images/plugin-compiler/data/test.sh | 12 -- 15 files changed, 427 insertions(+), 397 deletions(-) create mode 100644 ci/Dockerfile.slim create mode 100644 ci/goreleaser/goreleaser-el7.yml delete mode 100644 ci/images/plugin-compiler/data/basic-plugin/go.mod delete mode 100644 ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go delete mode 100644 ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go delete mode 100755 ci/images/plugin-compiler/data/test.sh diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 6b50254bf72..88bb5ca32ac 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -2,9 +2,11 @@ name: API integration Tests on: pull_request: + push: branches: - master - - release-** + - test/* + - release-* env: GOPRIVATE: github.com/TykTechnologies @@ -13,7 +15,7 @@ jobs: test: strategy: matrix: - go-version: [1.19.x] + go-version: [1.16.x] platform: [ubuntu-latest] arch: [amd64] node-version: [15.x] @@ -32,7 +34,7 @@ jobs: git config --global url."https://${TOKEN}@github.com".insteadOf "https://github.com" - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: tyk token: ${{ secrets.ORG_GH_TOKEN }} @@ -55,7 +57,7 @@ jobs: fi - name: Checkout test repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: TykTechnologies/tyk-automated-tests token: ${{ secrets.ORG_GH_TOKEN }} @@ -68,18 +70,18 @@ jobs: TOKEN: '${{ secrets.ORG_GH_TOKEN }}' run: | echo "branch=master" >> $GITHUB_OUTPUT - if [ ! -z "${{ github.head_ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.head_ref }}; then - echo "branch=${{ github.head_ref }}" >> $GITHUB_OUTPUT + if [ ! -z "${{ github.head_ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.head_ref }}; then + echo "branch=${{ github.head_ref }}" >> $GITHUB_OUTPUT fi - if [ ! -z "${{ github.base_ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.base_ref }}; then - echo "branch=${{ github.base_ref }}" >> $GITHUB_OUTPUT + if [ ! -z "${{ github.base_ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.base_ref }}; then + echo "branch=${{ github.base_ref }}" >> $GITHUB_OUTPUT fi - if [ ! -z "${{ github.ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.ref }}; then - echo "branch=${{ github.ref }}" >> $GITHUB_OUTPUT + if [ ! -z "${{ github.ref }}" ] && git ls-remote --exit-code --heads https://${TOKEN}@github.com/TykTechnologies/tyk-analytics ${{ github.ref }}; then + echo "branch=${{ github.ref }}" >> $GITHUB_OUTPUT fi - name: Checkout dashboard - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: TykTechnologies/tyk-analytics token: ${{ secrets.ORG_GH_TOKEN }} @@ -135,7 +137,7 @@ jobs: - name: Archive Integration tests report if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: api-test-report path: ./tyk-automated-tests/reports/ @@ -177,6 +179,6 @@ jobs: CLIENT_SECRET: ${{secrets.XRAY_CLIENT_SECRET}} BRANCH: ${{ github.ref }} - - name: Getting gateway logs on failure + - name: Getting docker logs on failure if: ${{ failure() }} - run: docker logs tyk-gateway + run: docker-compose -f ci/ci_testing_env.yml logs diff --git a/.github/workflows/base.yml b/.github/workflows/base.yml index 9b2883a8b54..3a93361227d 100644 --- a/.github/workflows/base.yml +++ b/.github/workflows/base.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout Tyk - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 1 diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 0f6485a1da8..76a20c23403 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout Tyk - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Golang uses: actions/setup-go@v2 diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml index 1e26109d3fb..d4ee129ad97 100644 --- a/.github/workflows/del-env.yml +++ b/.github/workflows/del-env.yml @@ -1,6 +1,11 @@ -# Generated by: gromit policy -# Generated on: Fri Jun 16 08:40:35 UTC 2023 + +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxREPO=tyk name: Retiring dev env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34b413dccc0..e52e703ec40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,11 @@ -# Generated by: gromit policy -# Generated on: Fri Jun 16 08:40:35 UTC 2023 +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxREPO=tyk # Distribution channels covered by this workflow # - Ubuntu and Debian @@ -20,6 +24,9 @@ on: branches: - master - release-** + - integration/** + - feature/** + - perf/** tags: - 'v*' @@ -43,8 +50,9 @@ jobs: debvers: 'ubuntu/xenial ubuntu/bionic debian/jessie' - golang_cross: 1.15 goreleaser: 'ci/goreleaser/goreleaser.yml' - rpmvers: 'el/8 el/9' - debvers: 'ubuntu/bionic ubuntu/focal ubuntu/jammy debian/buster debian/bullseye' + rpmvers: 'el/8' + debvers: 'ubuntu/focal debian/buster debian/bullseye' + outputs: tag: ${{ steps.targets.outputs.tag }} @@ -73,6 +81,7 @@ jobs: with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login to Cloudsmith if: startsWith(github.ref, 'refs/tags') uses: docker/login-action@v2 @@ -107,6 +116,8 @@ jobs: *.tar.gz *.txt.sig *.txt + + - name: Fix vendor run: | export GOPATH=/go @@ -120,9 +131,10 @@ jobs: mkdir -p /go/src/github.com/TykTechnologies/tyk cp -r ./* /go/src/github.com/TykTechnologies/tyk + - uses: goreleaser/goreleaser-action@v4 with: - version: latest + version: 1.18.2 args: release --clean -f ${{ matrix.goreleaser }} ${{ !startsWith(github.ref, 'refs/tags/') && ' --snapshot' || '' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -152,6 +164,8 @@ jobs: path: | dist/*.rpm !dist/*PAYG*.rpm + + ci: needs: - goreleaser @@ -162,6 +176,7 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 1 + - name: Setup Terraform uses: hashicorp/setup-terraform@v2 with: @@ -250,7 +265,7 @@ jobs: ORG_GH_TOKEN: ${{ secrets.ORG_GH_TOKEN }} upgrade-deb: - if: startsWith(github.ref, 'refs/tags') && !github.event.pull_request.draft + if: startsWith(github.ref, 'refs/tags') runs-on: ubuntu-latest needs: goreleaser strategy: @@ -284,8 +299,9 @@ jobs: ARG TARGETARCH COPY tyk-gateway*_${TARGETARCH}.deb /tyk-gateway.deb RUN apt-get update && apt-get install -y curl + RUN curl -fsSL https://packagecloud.io/install/repositories/tyk/tyk-gateway/script.deb.sh | bash && apt-get install -y tyk-gateway=3.0.8 - RUN dpkg -i tyk-gateway.deb + RUN dpkg -i tyk-gateway.deb RUN apt-get install -y jq RUN /opt/tyk-gateway/install/setup.sh --listenport=8080 --redishost=localhost --redisport=6379 --domain="" COPY ci/tests/api-functionality/api_test.sh / @@ -309,7 +325,7 @@ jobs: docker run --rm test-${{ matrix.distro }}-${{ matrix.arch }} upgrade-rpm: - if: startsWith(github.ref, 'refs/tags') && !github.event.pull_request.draft + if: startsWith(github.ref, 'refs/tags') needs: goreleaser runs-on: ubuntu-latest strategy: @@ -335,10 +351,11 @@ jobs: echo 'FROM registry.access.redhat.com/${{ matrix.distro }} COPY tyk-gateway*.x86_64.rpm /tyk-gateway.rpm RUN yum install -y curl + RUN curl -fsSL https://packagecloud.io/install/repositories/tyk/tyk-gateway/script.rpm.sh | bash && yum install -y tyk-gateway-3.0.8-1 RUN curl https://keyserver.tyk.io/tyk.io.rpm.signing.key.2020 -o tyk-gateway.key && rpm --import tyk-gateway.key RUN rpm --checksig tyk-gateway.rpm - RUN rpm -Uvh --force tyk-gateway.rpm + RUN rpm -Uvh --force tyk-gateway.rpm RUN curl -fSL https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 --output /usr/local/bin/jq && chmod a+x /usr/local/bin/jq RUN /opt/tyk-gateway/install/setup.sh --listenport=8080 --redishost=localhost --redisport=6379 --domain="" COPY ci/tests/api-functionality/data/api.json /opt/tyk-gateway/apps/ @@ -361,7 +378,7 @@ jobs: docker run --rm test-${{ matrix.distro }} smoke-tests: - if: startsWith(github.ref, 'refs/tags') && !github.event.pull_request.draft + if: startsWith(github.ref, 'refs/tags') needs: - goreleaser runs-on: ubuntu-latest @@ -401,6 +418,7 @@ jobs: fi done + # AWS updates only for stable releases aws-mktplace-byol: if: ( 'a' == 'b' ) @@ -432,3 +450,4 @@ jobs: packer build -var-file=${{ matrix.flavour }}.vars.json byol.pkr.hcl + diff --git a/ci/Dockerfile.slim b/ci/Dockerfile.slim new file mode 100644 index 00000000000..10d105ce6db --- /dev/null +++ b/ci/Dockerfile.slim @@ -0,0 +1,19 @@ + + +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxREPO=tyk + +FROM gcr.io/distroless/static-debian11 +WORKDIR /opt/tyk +COPY tyk . +COPY apps/app_sample.json apps/app_sample.json +COPY tyk.conf.example tyk.conf +ARG PORTS +EXPOSE $PORTS + +ENTRYPOINT ["/opt/tyk-gateway/tyk" ] +CMD [ "--conf=/opt/tyk-gateway/tyk.conf" ] diff --git a/ci/Dockerfile.std b/ci/Dockerfile.std index f1518f0864d..0e05fc6e5e0 100644 --- a/ci/Dockerfile.std +++ b/ci/Dockerfile.std @@ -1,31 +1,36 @@ -# Generated by: gromit policy -# Generated on: Fri Jun 16 08:40:35 UTC 2023 + +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxREPO=tyk FROM debian:bullseye-slim ARG TARGETARCH ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update \ - && apt-get dist-upgrade -y ca-certificates # Install curl and python3 -RUN apt-get install -y curl python3-setuptools libpython3.9 python3.9-dev \ +RUN apt update \ + && apt dist-upgrade -y ca-certificates curl \ + && apt install -y python3-setuptools libpython3.9 python3.9-dev \ && curl https://bootstrap.pypa.io/get-pip.py | python3 \ && pip3 install --only-binary ":all:" grpcio protobuf==3.20.1 - # Remove some things to decrease CVE surface -RUN apt-get remove -y --allow-remove-essential --auto-remove curl libtiff5 ncurses-base \ +RUN apt remove -y --auto-remove --allow-remove-essential curl libtiff5 ncurses-base \ && rm /usr/bin/passwd && rm /usr/sbin/adduser # Clean up caches, unwanted .a and .o files RUN rm -rf /root/.cache \ - && apt-get -y autoremove \ - && apt-get clean \ + && apt -y autoremove \ + && apt clean \ && rm -rf /usr/include/* \ && find /usr/lib -type f -name '*.a' -delete \ && find /usr/lib -type f -name '*.o' -delete + # Print included pip/python versions RUN pip3 --version && python3 --version @@ -41,6 +46,6 @@ WORKDIR /opt/tyk-gateway/ # Uncomment this to test in dev # COPY tyk . -ENTRYPOINT ["/opt/tyk-gateway/tyk" ] +ENTRYPOINT ["/opt/tyk-gateway/tyk" ] CMD [ "--conf=/opt/tyk-gateway/tyk.conf" ] diff --git a/ci/goreleaser/goreleaser-el7.yml b/ci/goreleaser/goreleaser-el7.yml new file mode 100644 index 00000000000..09e7fff871d --- /dev/null +++ b/ci/goreleaser/goreleaser-el7.yml @@ -0,0 +1,197 @@ + + +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxEL7_SUFFIX=-el7 -DxREPO=tyk + + +# Check the documentation at http://goreleaser.com +# This project needs CGO_ENABLED=1 and the cross-compiler toolchains for +# - arm64 +# - amd64 + + +builds: + - id: std-linux + + flags: + - -tags=goplugin + ldflags: + - -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser + goos: + - linux + goarch: + - amd64 + - id: std-arm64 + + flags: + - -tags=goplugin + ldflags: + - -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser + env: + - CC=aarch64-linux-gnu-gcc + goos: + - linux + goarch: + - arm64 + # static builds strip symbols and do not allow plugins + - id: static-amd64 + ldflags: + - -s -w -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser + - -linkmode external -extldflags -static + goos: + - linux + goarch: + - amd64 + + +nfpms: + - id: std + vendor: "Tyk Technologies Ltd" + homepage: "https://tyk.io" + maintainer: "Tyk " + description: Tyk API Gateway + package_name: tyk-gateway + builds: + + - std-linux + - std-arm64 + formats: + - deb + - rpm + contents: + - src: "README.md" + dst: "/opt/share/docs/tyk-gateway/README.md" + - src: "ci/install/*" + dst: "/opt/tyk-gateway/install" + - src: ci/install/inits/systemd/system/tyk-gateway.service + dst: /lib/systemd/system/tyk-gateway.service + - src: ci/install/inits/sysv/init.d/tyk-gateway + dst: /etc/init.d/tyk-gateway + + - src: /opt/tyk-gateway + dst: /opt/tyk + type: "symlink" + - src: "LICENSE.md" + dst: "/opt/share/docs/tyk-gateway/LICENSE.md" + - src: "apps/app_sample.*" + dst: "/opt/tyk-gateway/apps" + - src: "templates/*.json" + dst: "/opt/tyk-gateway/templates" + - src: "templates/playground/*" + dst: "/opt/tyk-gateway/templates/playground" + - src: "middleware/*.js" + dst: "/opt/tyk-gateway/middleware" + - src: "event_handlers/sample/*.js" + dst: "/opt/tyk-gateway/event_handlers/sample" + - src: "policies/*.json" + dst: "/opt/tyk-gateway/policies" + - src: "coprocess/*" + dst: "/opt/tyk-gateway/coprocess" + - src: tyk.conf.example + dst: /opt/tyk-gateway/tyk.conf + type: "config|noreplace" + scripts: + preinstall: "ci/install/before_install.sh" + postinstall: "ci/install/post_install.sh" + postremove: "ci/install/post_remove.sh" + bindir: "/opt/tyk-gateway" + overrides: + rpm: + file_name_template: '{{ .PackageName }}-{{ replace .Version "-" "~" }}-1.{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}' + replacements: + amd64: x86_64 + arm: aarch64 + arm64: aarch64 + deb: + file_name_template: '{{ .PackageName }}_{{ replace .Version "-" "~" }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}' + replacements: + arm: arm64 + rpm: + scripts: + posttrans: ci/install/post_trans.sh + signature: + key_file: tyk.io.signing.key + deb: + signature: + key_file: tyk.io.signing.key + type: origin + + + +publishers: + - name: tyk-gateway-unstable + env: + - PACKAGECLOUD_TOKEN={{ .Env.PACKAGECLOUD_TOKEN }} + - REPO=tyk/tyk-gateway-unstable + - RPMVERS={{ .Env.RPMVERS }} + - DEBVERS={{ .Env.DEBVERS }} + cmd: /pc.sh {{ .ArtifactPath }} + + +# This disables archives +archives: + - format: binary + allow_different_binary_count: true + +dockers: + +# Build plugin-compiler +- ids: + - std + image_templates: + - tykio/tyk-plugin-compiler:{{ .Tag }}-el7 + - "tykio/tyk-plugin-compiler:v{{ .Major }}.{{ .Minor }}{{.Prerelease}}-el7" + build_flag_templates: + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title=tyk-plugin-compiler" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--build-arg=TYK_GW_TAG={{ .Tag }}" + - "--build-arg=GOLANG_CROSS={{ .Env.GOLANG_CROSS }}" + goarch: amd64 + goos: linux + dockerfile: ci/images/plugin-compiler/Dockerfile + extra_files: + - ci/images/plugin-compiler + - go.mod + - apidef + - certs + - checkup + - cli + - config + - coprocess + - ctx + - dlpython + - dnscache + - gateway + - goplugin + - headers + - log + - regexp + - request + - rpc + - signature_validator + - storage + - tcp + - templates + - test + - testdata + - trace + - user + - internal + +checksum: + disable: true + +release: + disable: true + github: + owner: TykTechnologies + name: tyk + prerelease: auto + draft: true + name_template: "{{.ProjectName}}-v{{.Version}}" diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index fca30eab1f0..f050f17c826 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -1,12 +1,21 @@ -# Generated by: gromit policy -# Generated on: Fri Jun 16 08:40:35 UTC 2023 + + +# Generated by: tyk-ci/wf-gen +# Generated on: Friday 04 March 2022 11:40:32 AM UTC + +# Generation commands: +# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates +# m4 -E -DxREPO=tyk + # Check the documentation at http://goreleaser.com # This project needs CGO_ENABLED=1 and the cross-compiler toolchains for # - arm64 # - amd64 + builds: - id: std-linux + flags: - -tags=goplugin ldflags: @@ -15,8 +24,8 @@ builds: - linux goarch: - amd64 - binary: tyk - id: std-arm64 + flags: - -tags=goplugin ldflags: @@ -27,10 +36,20 @@ builds: - linux goarch: - arm64 - binary: tyk + # static builds strip symbols and do not allow plugins + - id: static-amd64 + ldflags: + - -s -w -X github.com/TykTechnologies/tyk/gateway.VERSION={{.Version}} -X github.com/TykTechnologies/tyk/gateway.Commit={{.FullCommit}} -X github.com/TykTechnologies/tyk/gateway.buildDate={{.Date}} -X github.com/TykTechnologies/tyk/gateway.builtBy=goreleaser + - -linkmode external -extldflags -static + goos: + - linux + goarch: + - amd64 + + dockers: -# Build tykio/tyk-gateway, docker.tyk.io/tyk-gateway/tyk-gateway (amd64) +# Build tykio/xDH_REPO, cloudsmith/xCOMPATIBILITY_NAME (amd64) - ids: - std image_templates: @@ -50,6 +69,7 @@ dockers: extra_files: - "ci/install/" - "README.md" + - "LICENSE.md" - "apps/app_sample.json" - "templates" @@ -59,42 +79,53 @@ dockers: - "coprocess" - "tyk.conf.example" -# Build gateway hybrid container amd64 +# Build tykio/xDH_REPO, cloudsmith/xCOMPATIBILITY_NAME (arm64) - ids: - std image_templates: - - "tykio/tyk-hybrid-docker:{{ .Tag }}-amd64" + - "tykio/tyk-gateway:{{ .Tag }}-arm64" + - "docker.tyk.io/tyk-gateway/tyk-gateway:{{ .Tag }}-arm64" build_flag_templates: - - "--platform=linux/amd64" + - "--build-arg=PORTS=8080" + - "--platform=linux/arm64" - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}-hybrid" + - "--label=org.opencontainers.image.title={{.ProjectName}}-arm64" - "--label=org.opencontainers.image.revision={{.FullCommit}}" - "--label=org.opencontainers.image.version={{.Version}}" use: buildx - goarch: amd64 + goarch: arm64 goos: linux - dockerfile: ci/images/hybrid/Dockerfile + dockerfile: ci/Dockerfile.std extra_files: - - "ci/images/hybrid/" -# Build tykio/tyk-gateway, docker.tyk.io/tyk-gateway/tyk-gateway (arm64) + - "ci/" + - "README.md" + - "LICENSE.md" + - "apps/app_sample.json" + - "templates" + - "middleware" + - "event_handlers/sample" + - "policies" + - "coprocess" + - "tyk.conf.example" + - ids: - - std + - static-amd64 image_templates: - - "tykio/tyk-gateway:{{ .Tag }}-arm64" - - "docker.tyk.io/tyk-gateway/tyk-gateway:{{ .Tag }}-arm64" + - "tykio/tyk-gateway:s{{ .Version }}" + - "tykio/tyk-gateway:s{{ .Major }}.{{ .Minor }}" + - "docker.tyk.io/tyk-gateway/tyk-gateway:s{{ .Version }}" + - "docker.tyk.io/tyk-gateway/tyk-gateway:s{{ .Major }}.{{ .Minor }}" build_flag_templates: - "--build-arg=PORTS=8080" - - "--platform=linux/arm64" - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}-slim" - "--label=org.opencontainers.image.revision={{.FullCommit}}" - "--label=org.opencontainers.image.version={{.Version}}" - use: buildx - goarch: arm64 + goarch: amd64 goos: linux - dockerfile: ci/Dockerfile.std + dockerfile: ci/Dockerfile.slim extra_files: - - "ci/install/" + - "ci/" - "README.md" - "LICENSE.md" - "apps/app_sample.json" @@ -105,6 +136,24 @@ dockers: - "coprocess" - "tyk.conf.example" +# Build gateway hybrid container amd64 +- ids: + - std + image_templates: + - "tykio/tyk-hybrid-docker:{{ .Tag }}-amd64" + build_flag_templates: + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}-hybrid" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + use: buildx + goarch: amd64 + goos: linux + dockerfile: ci/images/hybrid/Dockerfile + extra_files: + - "ci/images/hybrid/" + # Build gateway hybrid container arm64 - ids: - std @@ -123,12 +172,13 @@ dockers: extra_files: - "ci/images/hybrid/" + # Build plugin-compiler - ids: - std image_templates: - tykio/tyk-plugin-compiler:{{ .Tag }} - - tykio/tyk-plugin-compiler:v{{ .Major }}.{{ .Minor }}{{.Prerelease}} + - "tykio/tyk-plugin-compiler:v{{ .Major }}.{{ .Minor }}{{.Prerelease}}" build_flag_templates: - "--label=org.opencontainers.image.created={{.Date}}" - "--label=org.opencontainers.image.title=tyk-plugin-compiler" @@ -136,12 +186,37 @@ dockers: - "--label=org.opencontainers.image.version={{.Version}}" - "--build-arg=TYK_GW_TAG={{ .Tag }}" - "--build-arg=GOLANG_CROSS={{ .Env.GOLANG_CROSS }}" - - "--build-arg=GITHUB_SHA={{ .Env.GITHUB_SHA }}" goarch: amd64 goos: linux dockerfile: ci/images/plugin-compiler/Dockerfile extra_files: - ci/images/plugin-compiler + - go.mod + - apidef + - certs + - checkup + - cli + - config + - coprocess + - ctx + - dlpython + - dnscache + - gateway + - goplugin + - headers + - log + - regexp + - request + - rpc + - signature_validator + - storage + - tcp + - templates + - test + - testdata + - trace + - user + - internal docker_manifests: - name_template: tykio/tyk-gateway:{{ .Tag }} @@ -152,19 +227,22 @@ docker_manifests: image_templates: - tykio/tyk-gateway:{{ .Tag }}-amd64 - tykio/tyk-gateway:{{ .Tag }}-arm64 + - name_template: tykio/tyk-hybrid-docker:{{ .Tag }} image_templates: - tykio/tyk-hybrid-docker:{{ .Tag }}-amd64 - tykio/tyk-hybrid-docker:{{ .Tag }}-arm64 + nfpms: - id: std vendor: "Tyk Technologies Ltd" homepage: "https://tyk.io" maintainer: "Tyk " - description: Tyk Open Source API Gateway written in Go, supporting REST, GraphQL, TCP and gRPC protocols + description: Tyk API Gateway package_name: tyk-gateway builds: + - std-linux - std-arm64 formats: @@ -179,6 +257,7 @@ nfpms: dst: /lib/systemd/system/tyk-gateway.service - src: ci/install/inits/sysv/init.d/tyk-gateway dst: /etc/init.d/tyk-gateway + - src: /opt/tyk-gateway dst: /opt/tyk type: "symlink" @@ -227,6 +306,8 @@ nfpms: key_file: tyk.io.signing.key type: origin + + publishers: - name: tyk-gateway-unstable env: @@ -239,6 +320,7 @@ publishers: archives: - id: std-linux builds: + - std-linux - std-arm64 files: @@ -256,6 +338,7 @@ archives: - tyk.conf.example + checksum: disable: true diff --git a/ci/images/plugin-compiler/Dockerfile b/ci/images/plugin-compiler/Dockerfile index a62fed80ac4..6ade3829556 100644 --- a/ci/images/plugin-compiler/Dockerfile +++ b/ci/images/plugin-compiler/Dockerfile @@ -1,34 +1,23 @@ -ARG BASE_IMAGE -FROM ${BASE_IMAGE} +ARG GOLANG_CROSS=1.15 +FROM tykio/golang-cross:${GOLANG_CROSS} LABEL description="Image for plugin development" ENV TYK_GW_PATH=/go/src/github.com/TykTechnologies/tyk ENV GO111MODULE=on + # This directory will contain the plugin source and will be # mounted from the host box by the user using docker volumes ENV PLUGIN_SOURCE_PATH=/plugin-source RUN mkdir -p $TYK_GW_PATH $PLUGIN_SOURCE_PATH -RUN apt-get remove -y --allow-remove-essential --auto-remove mercurial \ - && rm /usr/bin/passwd && rm /usr/sbin/adduser - -ADD go.mod go.sum $TYK_GW_PATH -WORKDIR $TYK_GW_PATH -RUN go mod download - -ADD . $TYK_GW_PATH - -ARG GITHUB_SHA -ARG GITHUB_TAG -ARG BASE_IMAGE -ENV BASE_IMAGE ${BASE_IMAGE} -ENV GITHUB_SHA ${GITHUB_SHA} -ENV GITHUB_TAG ${GITHUB_TAG} - COPY ci/images/plugin-compiler/data/build.sh /build.sh RUN chmod +x /build.sh +COPY . $TYK_GW_PATH +RUN cd $TYK_GW_PATH && go mod vendor + ENTRYPOINT ["/build.sh"] + diff --git a/ci/images/plugin-compiler/data/basic-plugin/go.mod b/ci/images/plugin-compiler/data/basic-plugin/go.mod deleted file mode 100644 index f0793995cc2..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module example.com/basic-plugin - -go 1.19 diff --git a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go b/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go deleted file mode 100644 index 4d1be1d6517..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go +++ /dev/null @@ -1,196 +0,0 @@ -package main - -import ( - "bufio" - "bytes" - "encoding/base64" - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/buger/jsonparser" - - "github.com/TykTechnologies/tyk-pump/analytics" - "github.com/TykTechnologies/tyk/ctx" - "github.com/TykTechnologies/tyk/header" - "github.com/TykTechnologies/tyk/user" -) - -// MyPluginPre checks if session is NOT present, adds custom header -// with initial URI path and will be used as "pre" custom MW -func MyPluginPre(rw http.ResponseWriter, r *http.Request) { - session := ctx.GetSession(r) - if session != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - rw.Header().Add(header.XInitialURI, r.URL.RequestURI()) -} - -// MyPluginAuthCheck does custom auth and will be used as -// "auth_check" custom MW -func MyPluginAuthCheck(rw http.ResponseWriter, r *http.Request) { - // perform auth (only one token "abc" is allowed) - token := r.Header.Get(header.Authorization) - if token != "abc" { - rw.Header().Add(header.XAuthResult, "failed") - rw.WriteHeader(http.StatusForbidden) - _, _ = rw.Write([]byte("auth failed")) - return - } - - // create session - session := &user.SessionState{ - OrgID: "default", - Alias: "abc-session", - KeyID: token, - } - - ctx.SetSession(r, session, true, true) - rw.Header().Add(header.XAuthResult, "OK") -} - -// MyPluginPostKeyAuth checks if session is present, adds custom header with session-alias -// and will be used as "post_key_auth" custom MW -func MyPluginPostKeyAuth(rw http.ResponseWriter, r *http.Request) { - session := ctx.GetSession(r) - if session == nil { - rw.Header().Add(header.XSessionAlias, "not found") - rw.WriteHeader(http.StatusInternalServerError) - return - } - - rw.Header().Add(header.XSessionAlias, session.Alias) -} - -// MyPluginPost prepares and sends reply, will be used as "post" custom MW -func MyPluginPost(rw http.ResponseWriter, r *http.Request) { - - replyData := map[string]interface{}{ - "message": "post message", - } - - jsonData, err := json.Marshal(replyData) - if err != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - apiDefinition := ctx.GetDefinition(r) - if apiDefinition == nil { - rw.Header().Add("X-Plugin-Data", "null") - } else { - pluginConfig, ok := apiDefinition.ConfigData["my-context-data"].(string) - if !ok || pluginConfig == "" { - rw.Header().Add("X-Plugin-Data", "null") - } else { - rw.Header().Add("X-Plugin-Data", pluginConfig) - } - - } - rw.Header().Set(header.ContentType, header.ApplicationJSON) - rw.WriteHeader(http.StatusOK) - rw.Write(jsonData) -} - -// MyPluginResponse intercepts response from upstream which we can then manipulate -func MyPluginResponse(rw http.ResponseWriter, res *http.Response, req *http.Request) { - - res.Header.Add("X-Response-Added", "resp-added") - - var buf bytes.Buffer - - buf.Write([]byte(`{"message":"response injected message"}`)) - - res.Body = ioutil.NopCloser(&buf) - - apiDefinition := ctx.GetDefinition(req) - if apiDefinition == nil { - res.Header.Add("X-Plugin-Data", "null") - return - } - pluginConfig, ok := apiDefinition.ConfigData["my-context-data"].(string) - if !ok || pluginConfig == "" { - res.Header.Add("X-Plugin-Data", "null") - return - } - res.Header.Add("X-Plugin-Data", pluginConfig) -} - -func MyPluginPerPathFoo(rw http.ResponseWriter, r *http.Request) { - - rw.Header().Add("X-foo", "foo") - -} - -func MyPluginPerPathBar(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add("X-bar", "bar") - -} - -func MyPluginPerPathResp(rw http.ResponseWriter, r *http.Request) { - // prepare data to send - replyData := map[string]string{ - "current_time": "now", - } - - jsonData, err := json.Marshal(replyData) - if err != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - // send HTTP response from Golang plugin - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(http.StatusOK) - rw.Write(jsonData) -} - -func MyAnalyticsPluginDeleteHeader(record *analytics.AnalyticsRecord) { - str, err := base64.StdEncoding.DecodeString(record.RawResponse) - if err != nil { - return - } - - var b = &bytes.Buffer{} - b.Write(str) - - r := bufio.NewReader(b) - var resp *http.Response - resp, err = http.ReadResponse(r, nil) - if err != nil { - return - } - resp.Header.Del("Server") - var bNew bytes.Buffer - _ = resp.Write(&bNew) - record.RawResponse = base64.StdEncoding.EncodeToString(bNew.Bytes()) -} - -func MyAnalyticsPluginMaskJSONLoginBody(record *analytics.AnalyticsRecord) { - if record.ContentLength < 1 { - return - } - d, err := base64.StdEncoding.DecodeString(record.RawRequest) - if err != nil { - return - } - var mask = []byte("\"****\"") - const endOfHeaders = "\r\n\r\n" - paths := [][]string{ - {"email"}, - {"password"}, - {"data", "email"}, - {"data", "password"}, - } - if i := bytes.Index(d, []byte(endOfHeaders)); i > 0 || (i+4) < len(d) { - body := d[i+4:] - jsonparser.EachKey(body, func(idx int, _ []byte, _ jsonparser.ValueType, _ error) { - body, _ = jsonparser.Set(body, mask, paths[idx]...) - }, paths...) - if err == nil { - record.RawRequest = base64.StdEncoding.EncodeToString(append(d[:i+4], body...)) - } - } -} diff --git a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go b/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go deleted file mode 100644 index c3a8ff89c85..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "bytes" - "encoding/base64" - "fmt" - - "github.com/buger/jsonparser" - - "github.com/TykTechnologies/tyk-pump/analytics" -) - -func ExampleMyAnalyticsPluginDeleteHeader() { - record := analytics.AnalyticsRecord{ - ContentLength: 5, - RawResponse: base64.StdEncoding.EncodeToString([]byte("HTTP/1.1 200 OK\r\nServer: golang\r\nContent-Length: 5\r\n\r\nHello")), - } - MyAnalyticsPluginDeleteHeader(&record) - data, _ := base64.StdEncoding.DecodeString(record.RawResponse) - fmt.Printf("%q", string(data)) - // Output: "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello" -} - -func ExampleMyAnalyticsPluginMaskJSONLoginBody() { - record := analytics.AnalyticsRecord{ - ContentLength: 72, - RawRequest: base64.StdEncoding.EncodeToString([]byte("POST / HTTP/1.1\r\nHost: server.com\r\nContent-Length: 72\r\n\r\n{\"email\": \"m\", \"password\": \"p\", \"data\": {\"email\": \"m\", \"password\": \"p\"}}")), - } - MyAnalyticsPluginMaskJSONLoginBody(&record) - data, _ := base64.StdEncoding.DecodeString(record.RawRequest) - const endOfHeaders = "\r\n\r\n" - paths := [][]string{ - {"email"}, - {"password"}, - {"data", "email"}, - {"data", "password"}, - } - if i := bytes.Index(data, []byte(endOfHeaders)); i > 0 || (i+4) < len(data) { - jsonparser.EachKey(data[i+4:], func(_ int, v []byte, _ jsonparser.ValueType, _ error) { - fmt.Println(string(v)) - }, paths...) - } - // Output: **** - //**** - //**** - //**** -} diff --git a/ci/images/plugin-compiler/data/build.sh b/ci/images/plugin-compiler/data/build.sh index 0d8b919bbc0..e193e189743 100755 --- a/ci/images/plugin-compiler/data/build.sh +++ b/ci/images/plugin-compiler/data/build.sh @@ -1,34 +1,10 @@ #!/bin/bash -set -e - -GATEWAY_VERSION=$(echo $GITHUB_TAG | perl -n -e'/v(\d+).(\d+).(\d+)/'' && print "v$1\.$2\.$3"') - -# Plugin compiler arguments: -# -# - 1. plugin_name = vendor-plugin.so -# - 2. plugin_id = optional, sets build folder to `/opt/plugin_{plugin_name}{plugin_id}` -# - 3. GOOS = optional override of GOOS -# - 4. GOARCH = optional override of GOARCH -# -# The script will build a plugin named according to the following: -# -# - `{plugin_name%.*}_{GATEWAY_VERSION}_{GOOS}_{GOARCH}.so` -# -# If GOOS and GOARCH are not set, it will build `{plugin_name}`. -# -# Example command: ./build.sh -# Example output: tyk-extras_5.0.0_linux_amd64.so +set -xe plugin_name=$1 plugin_id=$2 -GOOS=${3:-$(go env GOOS)} -GOARCH=${4:-$(go env GOARCH)} -# Some defaults that can be overriden with env -WORKSPACE_ROOT=$(dirname $TYK_GW_PATH) - -PLUGIN_SOURCE_PATH=${PLUGIN_SOURCE_PATH:-"/plugin-source"} -PLUGIN_BUILD_PATH=${PLUGIN_BUILD_PATH:-"${WORKSPACE_ROOT}/plugin_${plugin_name%.*}$plugin_id"} +PLUGIN_BUILD_PATH="/go/src/plugin_${plugin_name%.*}$plugin_id" function usage() { cat < Date: Tue, 4 Jul 2023 15:21:09 +0300 Subject: [PATCH 08/33] Merging to release-4-lts: TT-9177 obsfuscate key on log (#5152) TT-9177 obsfuscate key on log (#5152) ## Description Obsfuscated the keys on logging, if someone would like to see the whole key printed in the logs then they should enable `enable_key_logging` in the configuration of the gateways ## Related Issue https://tyktech.atlassian.net/browse/TT-9177 ## Motivation and Context ## How This Has Been Tested Manually tested running an MDCB env ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why Co-authored-by: Zaid Albirawi --- gateway/api.go | 6 +++--- gateway/rpc_storage_handler.go | 8 ++++---- storage/redis_cluster.go | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/gateway/api.go b/gateway/api.go index 3b227c3541f..42c786511e0 100644 --- a/gateway/api.go +++ b/gateway/api.go @@ -731,7 +731,7 @@ func (gw *Gateway) handleDeleteKey(keyName, orgID, apiID string, resetQuota bool log.WithFields(logrus.Fields{ "prefix": "api", - "key": keyName, + "key": gw.obfuscateKey(keyName), "status": "ok", }).Info("Deleted key across all APIs.") @@ -761,7 +761,7 @@ func (gw *Gateway) handleDeleteKey(keyName, orgID, apiID string, resetQuota bool log.WithFields(logrus.Fields{ "prefix": "api", - "key": keyName, + "key": gw.obfuscateKey(keyName), "status": "ok", }).Info("Deleted key.") @@ -782,7 +782,7 @@ func (gw *Gateway) handleDeleteHashedKeyWithLogs(keyName, orgID, apiID string, r log.WithFields(logrus.Fields{ "prefix": "api", - "key": keyName, + "key": gw.obfuscateKey(keyName), "status": "ok", }).Info("Deleted hashed key across all APIs.") diff --git a/gateway/rpc_storage_handler.go b/gateway/rpc_storage_handler.go index 8ab9bc7e41d..062504d7d43 100644 --- a/gateway/rpc_storage_handler.go +++ b/gateway/rpc_storage_handler.go @@ -142,7 +142,7 @@ func (r *RPCStorageHandler) hashKey(in string) string { func (r *RPCStorageHandler) fixKey(keyName string) string { setKeyName := r.KeyPrefix + r.hashKey(keyName) - log.Debug("Input key was: ", setKeyName) + log.Debug("Input key was: ", r.Gw.obfuscateKey(setKeyName)) return setKeyName } @@ -424,8 +424,8 @@ func (r *RPCStorageHandler) GetKeysAndValues() map[string]string { // DeleteKey will remove a key from the database func (r *RPCStorageHandler) DeleteKey(keyName string) bool { - log.Debug("DEL Key was: ", keyName) - log.Debug("DEL Key became: ", r.fixKey(keyName)) + log.Debug("DEL Key was: ", r.Gw.obfuscateKey(keyName)) + log.Debug("DEL Key became: ", r.Gw.obfuscateKey(r.fixKey(keyName))) ok, err := rpc.FuncClientSingleton("DeleteKey", r.fixKey(keyName)) if err != nil { rpc.EmitErrorEventKv( @@ -894,7 +894,7 @@ func (r *RPCStorageHandler) ProcessKeySpaceChanges(keys []string, orgId string) _, status = r.Gw.handleDeleteHashedKey(splitKeys[0], orgId, "", resetQuota) r.Gw.getSessionAndCreate(splitKeys[0], r, true, orgId) } else { - log.Info("--> removing cached key: ", key) + log.Info("--> removing cached key: ", r.Gw.obfuscateKey(key)) // in case it's an username (basic auth) then generate the token if storage.TokenOrg(key) == "" { key = r.Gw.generateToken(orgId, key) diff --git a/storage/redis_cluster.go b/storage/redis_cluster.go index a08b2593926..26f8791a42c 100644 --- a/storage/redis_cluster.go +++ b/storage/redis_cluster.go @@ -584,8 +584,6 @@ func (r *RedisCluster) DeleteKey(keyName string) bool { log.Debug(err) return false } - log.Debug("DEL Key was: ", keyName) - log.Debug("DEL Key became: ", r.fixKey(keyName)) singleton, err := r.singleton() if err != nil { From 6102d718c5a50b2dbd3ca2cf80904a3169515902 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 3 Oct 2023 08:48:57 +0200 Subject: [PATCH 09/33] Go mod tidy (#5579) Fix go.mod somehow in dirty state Co-authored-by: Tit Petric --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index a8d1fa1a799..260ad920821 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,6 @@ require ( github.com/go-redis/redis/v8 v8.3.1 github.com/gocraft/health v0.0.0-20170925182251-8675af27fef0 github.com/gofrs/uuid v3.3.0+incompatible - github.com/golang/mock v1.4.1 github.com/golang/protobuf v1.4.2 github.com/google/btree v1.0.0 // indirect github.com/google/go-cmp v0.5.6 // indirect From 06fcdde26b06c901ea01e31d5d0962f7403de241 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Wed, 4 Oct 2023 08:54:30 +0200 Subject: [PATCH 10/33] [tests] Fix TestGroupResetHandler (#5583) Update a failing test. Co-authored-by: Tit Petric --- gateway/api_test.go | 91 ++++++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/gateway/api_test.go b/gateway/api_test.go index aa991dab61c..66960b78d40 100644 --- a/gateway/api_test.go +++ b/gateway/api_test.go @@ -1492,33 +1492,59 @@ func TestUpdateOauthClientHandler(t *testing.T) { func TestGroupResetHandler(t *testing.T) { ts := StartTest(nil) - defer ts.Close() + tryReloadCount := 100 + reloadCount := 0 + + didSubscribe := make(chan bool, 1) + didReload := make(chan bool, tryReloadCount) - didSubscribe := make(chan bool) - didReload := make(chan bool) cacheStore := storage.RedisCluster{RedisController: ts.Gw.RedisController} cacheStore.Connect() + // Test usually takes 0.05sec or so, timeout after 1s + ctx, cancel := context.WithTimeout(ts.Gw.ctx, time.Second) + defer cancel() + + // Using waitgroup to test cancellation + var wg sync.WaitGroup + wg.Add(1) + go func() { - err := cacheStore.StartPubSubHandler(context.Background(), RedisPubSubChannel, func(v interface{}) { + // Clean up resources on exit + defer func() { + close(didReload) + close(didSubscribe) + wg.Done() + }() + + err := cacheStore.StartPubSubHandler(ctx, RedisPubSubChannel, func(v interface{}) { switch x := v.(type) { case *redis.Subscription: didSubscribe <- true case *redis.Message: notf := Notification{Gw: ts.Gw} - if err := json.Unmarshal([]byte(x.Payload), ¬f); err != nil { - t.Error(err) - } + + err := json.Unmarshal([]byte(x.Payload), ¬f) + assert.NoError(t, err) + if notf.Command == NoticeGroupReload { didReload <- true + reloadCount++ } } }) - if err != nil { - t.Log(err) - t.Fail() - close(didReload) + + select { + case <-ctx.Done(): + // A cancelled context is expected at the end + return + default: } + + // Apart from a cancelled context, any error is + // considered a fatal error. + require.NoError(t, err) + }() uri := "/tyk/reload/group" @@ -1529,29 +1555,42 @@ func TestGroupResetHandler(t *testing.T) { ts.Gw.LoadSampleAPI(apiTestDef) - recorder := httptest.NewRecorder() - // If we don't wait for the subscription to be done, we might do // the reload before pub/sub is in place to receive our message. <-didSubscribe - req := ts.withAuth(TestReq(t, "GET", uri, nil)) - ts.mainRouter().ServeHTTP(recorder, req) + // Do a loop of tryReloadCount reloads + for try := 1; try <= tryReloadCount; try++ { + req := ts.withAuth(TestReq(t, "GET", uri, nil)) - if recorder.Code != 200 { - t.Fatal("Hot reload (group) failed, response code was: ", recorder.Code) - } + recorder := httptest.NewRecorder() + ts.mainRouter().ServeHTTP(recorder, req) - ts.Gw.apisMu.RLock() - if len(ts.Gw.apisByID) == 0 { - t.Fatal("Hot reload (group) was triggered but no APIs were found.") + assert.Equal(t, http.StatusOK, recorder.Code, "Hot reload (group) failed") + + ts.Gw.apisMu.RLock() + require.Len(t, ts.Gw.apisByID, 1, "Unexpected API count after hot reload (group) was triggered.") + ts.Gw.apisMu.RUnlock() + + // We wait for the right notification (NoticeGroupReload), other + // type of notifications may be received during tests, as this + // is the cluster channel: + select { + case <-ctx.Done(): + t.Fatalf("Timeout waiting for reload signal, registered %d reloads", reloadCount) + case ok := <-didReload: + require.True(t, ok, "Reload failed (closed pubsub?)") + } } - ts.Gw.apisMu.RUnlock() - // We wait for the right notification (NoticeGroupReload), other - // type of notifications may be received during tests, as this - // is the cluster channel: - <-didReload + // Close our *Test object, ensuring a cancelled context + ts.Close() + + // Wait for our pubsub loop to exit + wg.Wait() + + // Assert total reload count matches expected value + assert.Equal(t, tryReloadCount, reloadCount, "Unexpected number of reloads registered from pubsub") } func TestHotReloadSingle(t *testing.T) { From 77a1362262ec37e0ef11989e70eac4de08164c65 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Thu, 5 Oct 2023 08:22:25 +0200 Subject: [PATCH 11/33] [TT-9987] [4-lts] Fix plugin compiler cves (#5578) https://tyktech.atlassian.net/browse/TT-9987 --------- Co-authored-by: Tit Petric --- Taskfile.yml | 20 ++++++++++++++++++++ ci/goreleaser/goreleaser-el7.yml | 8 +++++--- ci/goreleaser/goreleaser.yml | 8 +++++--- ci/images/plugin-compiler/Dockerfile | 17 ++++++++++++++++- 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 Taskfile.yml diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 00000000000..3fef278c20d --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,20 @@ +--- +version: "3" + +tasks: + plugin-compiler: + desc: "Build and test plugin compiler" + cmds: + - task: plugin-compiler:build + - task: plugin-compiler:test + + plugin-compiler:build: + desc: "Build plugin compiler" + cmds: + - docker build --progress=plain --no-cache --build-arg GOLANG_CROSS=1.15-el7 -t internal/plugin-compiler-el7 -f ci/images/plugin-compiler/Dockerfile . + - docker build --progress=plain --no-cache --build-arg GOLANG_CROSS=1.15 -t internal/plugin-compiler -f ci/images/plugin-compiler/Dockerfile . + + plugin-compiler:test: + desc: "Test plugin compiler" + cmds: + - echo "Not implemented" diff --git a/ci/goreleaser/goreleaser-el7.yml b/ci/goreleaser/goreleaser-el7.yml index 09e7fff871d..1dec3cc4879 100644 --- a/ci/goreleaser/goreleaser-el7.yml +++ b/ci/goreleaser/goreleaser-el7.yml @@ -156,8 +156,6 @@ dockers: goos: linux dockerfile: ci/images/plugin-compiler/Dockerfile extra_files: - - ci/images/plugin-compiler - - go.mod - apidef - certs - checkup @@ -170,6 +168,7 @@ dockers: - gateway - goplugin - headers + - internal - log - regexp - request @@ -182,7 +181,10 @@ dockers: - testdata - trace - user - - internal + - go.mod + - go.sum + - main.go + - ci/images/plugin-compiler checksum: disable: true diff --git a/ci/goreleaser/goreleaser.yml b/ci/goreleaser/goreleaser.yml index f050f17c826..cb2d7529f41 100644 --- a/ci/goreleaser/goreleaser.yml +++ b/ci/goreleaser/goreleaser.yml @@ -190,8 +190,6 @@ dockers: goos: linux dockerfile: ci/images/plugin-compiler/Dockerfile extra_files: - - ci/images/plugin-compiler - - go.mod - apidef - certs - checkup @@ -204,6 +202,7 @@ dockers: - gateway - goplugin - headers + - internal - log - regexp - request @@ -216,7 +215,10 @@ dockers: - testdata - trace - user - - internal + - go.mod + - go.sum + - main.go + - ci/images/plugin-compiler docker_manifests: - name_template: tykio/tyk-gateway:{{ .Tag }} diff --git a/ci/images/plugin-compiler/Dockerfile b/ci/images/plugin-compiler/Dockerfile index 6ade3829556..1ba6448da5d 100644 --- a/ci/images/plugin-compiler/Dockerfile +++ b/ci/images/plugin-compiler/Dockerfile @@ -3,6 +3,9 @@ ARG GOLANG_CROSS=1.15 FROM tykio/golang-cross:${GOLANG_CROSS} LABEL description="Image for plugin development" +ARG GOLANG_CROSS=1.15 +ENV GOLANG_CROSS ${GOLANG_CROSS} + ENV TYK_GW_PATH=/go/src/github.com/TykTechnologies/tyk ENV GO111MODULE=on @@ -13,6 +16,19 @@ ENV PLUGIN_SOURCE_PATH=/plugin-source RUN mkdir -p $TYK_GW_PATH $PLUGIN_SOURCE_PATH +RUN apt-get purge --auto-remove -y mercurial ruby-dev 'python*' 'libpython*' openssh-client + +# Update sources list to point to archive.debian.org (EOL) +# COPY ci/images/plugin-compiler /tmp/plugin-compiler +# RUN bash -c "cp /tmp/plugin-compiler/sources.list/$(lsb_release -cs) /etc/apt/sources.list" + +RUN if [ "${GOLANG_CROSS}" = "1.15" ]; then apt-get update ; apt-get -y dist-upgrade; fi + +# Ensure git remains installed (required) +RUN git --version + +RUN rm /usr/bin/passwd && rm /usr/sbin/adduser + COPY ci/images/plugin-compiler/data/build.sh /build.sh RUN chmod +x /build.sh @@ -20,4 +36,3 @@ COPY . $TYK_GW_PATH RUN cd $TYK_GW_PATH && go mod vendor ENTRYPOINT ["/build.sh"] - From 7233874269af7544e873dcca48b91fdf37ee1dbf Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 6 Oct 2023 08:43:19 +0300 Subject: [PATCH 12/33] Merging to release-4-lts: [TT-7127] Fix goplugin invalid memory address or nil pointer dereference (#5589) (#5594) [TT-7127] Fix goplugin invalid memory address or nil pointer dereference (#5589) https://tyktech.atlassian.net/browse/TT-7127 Closes #4198 #4197 Signed-off-by: Chenyang Yan Co-authored-by: Chenyang Yan [TT-7127]: https://tyktech.atlassian.net/browse/TT-7127?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Tit Petric Co-authored-by: Tit Petric --- gateway/mw_go_plugin.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gateway/mw_go_plugin.go b/gateway/mw_go_plugin.go index 6a97a4be36a..16e45e83351 100644 --- a/gateway/mw_go_plugin.go +++ b/gateway/mw_go_plugin.go @@ -156,13 +156,16 @@ func (m *GoPluginMiddleware) goPluginFromRequest(r *http.Request) (*GoPluginMidd return perPathPerMethodGoPlugin.(*GoPluginMiddleware), found } func (m *GoPluginMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, conf interface{}) (err error, respCode int) { - // if a Go plugin is found for this path, override the base handler and logger: logger := m.logger handler := m.handler + successHandler := m.successHandler + if !m.APILevel { + // if a Go plugin is found for this path, override the base handler and logger if pluginMw, found := m.goPluginFromRequest(r); found { logger = pluginMw.logger handler = pluginMw.handler + successHandler = &SuccessHandler{BaseMiddleware: m.BaseMiddleware} } else { return nil, http.StatusOK // next middleware } @@ -226,7 +229,7 @@ func (m *GoPluginMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Reque m.logger.WithError(err).Error("Failed to process request with Go-plugin middleware func") default: // record 2XX to analytics - m.successHandler.RecordHit(r, Latency{Total: int64(ms)}, rw.statusCodeSent, rw.getHttpResponse(r)) + successHandler.RecordHit(r, Latency{Total: int64(ms)}, rw.statusCodeSent, rw.getHttpResponse(r)) // no need to continue passing this request down to reverse proxy respCode = mwStatusRespond From c6ff6cc926afd97cf3daa6c0546e83054f7ddc6b Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 20 Oct 2023 21:49:51 +0300 Subject: [PATCH 13/33] Merging to release-4-lts: [10308] Hide expected signature from logs in HMAC (#5648) [10308] Hide expected signature from logs in HMAC (#5648) This PR removes the expected HMAC signature from the logs which are printed when there is a mismatch. --- gateway/mw_http_signature_validation.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gateway/mw_http_signature_validation.go b/gateway/mw_http_signature_validation.go index 5eb315e3f51..c3eb8ba0125 100644 --- a/gateway/mw_http_signature_validation.go +++ b/gateway/mw_http_signature_validation.go @@ -184,8 +184,7 @@ func (hm *HTTPSignatureValidationMiddleware) ProcessRequest(w http.ResponseWrite if !matchPass { logger.WithFields(logrus.Fields{ - "expected": encodedSignature, - "got": fieldValues.Signature, + "got": fieldValues.Signature, }).Error("Signature string does not match!") return hm.authorizationError(r) } From 1e2370a6dc7db6d6c58f875dab737213272d0f35 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 25 Oct 2023 12:12:22 +0300 Subject: [PATCH 14/33] Merging to release-4-lts: [TT-10329] fix getargspec removal from python stdlib in 3.11 (deprecated since python 3.0) (#5664) [TT-10329] fix getargspec removal from python stdlib in 3.11 (deprecated since python 3.0) (#5664) https://tyktech.atlassian.net/browse/TT-10329 --------- Co-authored-by: Tit Petric --- coprocess/python/tyk/decorators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coprocess/python/tyk/decorators.py b/coprocess/python/tyk/decorators.py index 49d3a31eb57..3faa19efd5b 100644 --- a/coprocess/python/tyk/decorators.py +++ b/coprocess/python/tyk/decorators.py @@ -1,4 +1,4 @@ -from inspect import getargspec +from inspect import getfullargspec class HandlerDecorator(object): @@ -14,7 +14,7 @@ class Hook(object): def __init__(self, f): self.name = f.__name__ self.f = f - self.arg_count = len(getargspec(f)[0]) + self.arg_count = len(getfullargspec(f)[0]) def __call__(self, *args, **kwargs): if self.arg_count == 3: From 2988f8b3d09fdc4a90012c12a63e6b11f16e7f2b Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 12:15:20 +0300 Subject: [PATCH 15/33] Merging to release-4-lts: Merging to release-4.3.8: [TT-9964] Prevent new idle connections to be generated. (#5526) Merging to release-4.3.8: [TT-9964] Prevent new idle connections to be generated. (#5526) [TT-9964] Prevent new idle connections to be generated. (#5526) --- gateway/api_definition.go | 6 ++++++ gateway/api_loader.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gateway/api_definition.go b/gateway/api_definition.go index 932d38a9e9c..513f2667bcc 100644 --- a/gateway/api_definition.go +++ b/gateway/api_definition.go @@ -231,6 +231,12 @@ func (s *APISpec) Release() { if s.JSVM.VM != nil { s.JSVM.DeInit() } + + if s.HTTPTransport != nil { + // Prevent new idle connections to be generated. + s.HTTPTransport.transport.DisableKeepAlives = true + s.HTTPTransport.transport.CloseIdleConnections() + } } // Validate returns nil if s is a valid spec and an error stating why the spec is not valid. diff --git a/gateway/api_loader.go b/gateway/api_loader.go index cbb9926dcd3..5e61e3a1a59 100644 --- a/gateway/api_loader.go +++ b/gateway/api_loader.go @@ -953,7 +953,7 @@ func (gw *Gateway) loadApps(specs []*APISpec) { for _, spec := range specs { curSpec, ok := gw.apisByID[spec.APIID] - if ok && curSpec.Checksum != spec.Checksum { + if ok && shouldReloadSpec(curSpec, spec) { curSpec.Release() } } From 4234213c70f32678d6f5768d7b23b781166a88bd Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 12:46:48 +0300 Subject: [PATCH 16/33] Merging to release-4-lts: [TT-8547] Fix websocket error proxying (#4918) [TT-8547] Fix websocket error proxying (#4918) ## Description Upgrade websocket only when server responded with 101. Fixes the case when websocket have own authentification, so we can proxy this error. ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --- gateway/reverse_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/reverse_proxy.go b/gateway/reverse_proxy.go index a4bfc27b8e7..468e0ffb096 100644 --- a/gateway/reverse_proxy.go +++ b/gateway/reverse_proxy.go @@ -1381,7 +1381,7 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques upgrade, _ := p.IsUpgrade(req) // Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc) - if upgrade { + if upgrade && res.StatusCode == 101 { if err := p.handleUpgradeResponse(rw, outreq, res); err != nil { p.ErrorHandler.HandleError(rw, logreq, err.Error(), http.StatusInternalServerError, true) return ProxyResponse{UpstreamLatency: upstreamLatency} From 4ada3e509b0ef05019eef5328534f484deb3d28f Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Mon, 6 Nov 2023 11:14:26 +0100 Subject: [PATCH 17/33] [TT-10414] [release-4-lts] Fix python coprocess tests, pin protobuf dependency in CI (#5737) Co-authored-by: Tit Petric --- .github/workflows/ci-tests.yml | 6 +- .../coprocess_id_extractor_python_test.go | 191 +++++++++++------- coprocess/python/coprocess_python_test.go | 106 ++++++---- 3 files changed, 185 insertions(+), 118 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 76a20c23403..4ee45a0091c 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -21,7 +21,9 @@ jobs: steps: - name: Checkout Tyk - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} - name: Setup Golang uses: actions/setup-go@v2 @@ -42,7 +44,7 @@ jobs: python -m pip install --upgrade pip pip install setuptools pip install google - pip install protobuf + pip install 'protobuf==4.24.4' - name: Start Redis uses: supercharge/redis-github-action@1.1.0 diff --git a/coprocess/python/coprocess_id_extractor_python_test.go b/coprocess/python/coprocess_id_extractor_python_test.go index 208b3b62dc1..41e896f7739 100644 --- a/coprocess/python/coprocess_id_extractor_python_test.go +++ b/coprocess/python/coprocess_id_extractor_python_test.go @@ -3,16 +3,40 @@ package python import ( "net/http" "net/url" + "strings" "testing" - "time" "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/gateway" + "github.com/TykTechnologies/tyk/internal/uuid" "github.com/TykTechnologies/tyk/test" ) -var pythonIDExtractorHeaderValue = map[string]string{ - "manifest.json": ` +var pythonIDExtractorHeaderValue = func(token string) map[string]string { + middleware := ` +import time +from tyk.decorators import * +from gateway import TykGateway as tyk + +counter = 0 + +@Hook +def MyAuthHook(request, session, metadata, spec): + global counter + counter = counter + 1 + auth_header = request.get_header('Authorization') + if auth_header == 'valid_token' and counter < 2: + session.rate = 1000.0 + session.per = 1.0 + session.id_extractor_deadline = int(time.time()) + 60 + metadata["token"] = "valid_token" + return request, session, metadata + ` + + middleware = strings.ReplaceAll(middleware, "valid_token", token) + + return map[string]string{ + "manifest.json": ` { "file_list": [ "middleware.py" @@ -32,10 +56,16 @@ var pythonIDExtractorHeaderValue = map[string]string{ } } `, - "middleware.py": ` + "middleware.py": middleware, + } +} + +var pythonIDExtractorFormValue = func(token string) map[string]string { + middleware := ` import time from tyk.decorators import * from gateway import TykGateway as tyk +from urllib import parse counter = 0 @@ -43,18 +73,19 @@ counter = 0 def MyAuthHook(request, session, metadata, spec): global counter counter = counter + 1 - auth_header = request.get_header('Authorization') - if auth_header == 'valid_token' and counter < 2: + auth_param = parse.parse_qs(request.object.body)["auth"] + if auth_param and auth_param[0] == 'valid_token' and counter < 2: session.rate = 1000.0 session.per = 1.0 session.id_extractor_deadline = int(time.time()) + 60 metadata["token"] = "valid_token" return request, session, metadata - `, -} +` -var pythonIDExtractorFormValue = map[string]string{ - "manifest.json": ` + middleware = strings.ReplaceAll(middleware, "valid_token", token) + + return map[string]string{ + "manifest.json": ` { "file_list": [ "middleware.py" @@ -74,30 +105,36 @@ var pythonIDExtractorFormValue = map[string]string{ } } `, - "middleware.py": ` + "middleware.py": middleware, + } +} + +var pythonIDExtractorHeaderRegex = func(token string) map[string]string { + middleware := ` import time from tyk.decorators import * from gateway import TykGateway as tyk -from urllib import parse counter = 0 @Hook def MyAuthHook(request, session, metadata, spec): + print("MyAuthHook3 is called") global counter counter = counter + 1 - auth_param = parse.parse_qs(request.object.body)["auth"] - if auth_param and auth_param[0] == 'valid_token' and counter < 2: + _, auth_header = request.get_header('Authorization').split('-') + if auth_header and auth_header == '12345' and counter < 2: session.rate = 1000.0 session.per = 1.0 session.id_extractor_deadline = int(time.time()) + 60 metadata["token"] = "valid_token" return request, session, metadata -`, -} + ` -var pythonIDExtractorHeaderRegex = map[string]string{ - "manifest.json": ` + middleware = strings.ReplaceAll(middleware, "valid_token", token) + + return map[string]string{ + "manifest.json": ` { "file_list": [ "middleware.py" @@ -119,26 +156,8 @@ var pythonIDExtractorHeaderRegex = map[string]string{ } } `, - "middleware.py": ` -import time -from tyk.decorators import * -from gateway import TykGateway as tyk - -counter = 0 - -@Hook -def MyAuthHook(request, session, metadata, spec): - print("MyAuthHook3 is called") - global counter - counter = counter + 1 - _, auth_header = request.get_header('Authorization').split('-') - if auth_header and auth_header == '12345' and counter < 2: - session.rate = 1000.0 - session.per = 1.0 - session.id_extractor_deadline = int(time.time()) + 60 - metadata["token"] = "valid_token" - return request, session, metadata - `, + "middleware.py": middleware, + } } /* Value Extractor tests, using "header" source */ @@ -146,59 +165,79 @@ def MyAuthHook(request, session, metadata, spec): // Our `pythonBundleWithAuthCheck` plugin restrict more then 1 call // With ID extractor, it should run multiple times (because cache) func TestValueExtractorHeaderSource(t *testing.T) { - test.Flaky(t) - ts := gateway.StartTest(nil, gateway.TestConfig{ - CoprocessConfig: config.CoProcessConfig{ - EnableCoProcess: true, - PythonPathPrefix: pkgPath, - PythonVersion: "3.5", - }, - Delay: 10 * time.Millisecond, - }) - defer ts.Close() - - spec := gateway.BuildAPI(func(spec *gateway.APISpec) { - spec.Proxy.ListenPath = "/" - spec.UseKeylessAccess = false - spec.EnableCoProcessAuth = true - })[0] t.Run("Header value", func(t *testing.T) { - bundleID := ts.RegisterBundle("id_extractor_header_value", pythonIDExtractorHeaderValue) - spec.CustomMiddlewareBundle = bundleID - spec.APIID = "api1" - - ts.Gw.LoadAPI(spec) - time.Sleep(1 * time.Second) + ts := gateway.StartTest(nil, gateway.TestConfig{ + CoprocessConfig: config.CoProcessConfig{ + EnableCoProcess: true, + PythonPathPrefix: pkgPath, + }, + }) + defer ts.Close() + + validToken := uuid.NewHex() + bundleID := ts.RegisterBundle("id_extractor_header_value", pythonIDExtractorHeaderValue(validToken)) + + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { + spec.Proxy.ListenPath = "/" + spec.UseKeylessAccess = false + spec.EnableCoProcessAuth = true + spec.CustomMiddlewareBundle = bundleID + spec.APIID = "api1" + }) ts.Run(t, []test.TestCase{ - {Path: "/", Headers: map[string]string{"Authorization": "valid_token"}, Code: http.StatusOK}, - {Path: "/", Headers: map[string]string{"Authorization": "valid_token"}, Code: http.StatusOK}, + {Path: "/", Headers: map[string]string{"Authorization": validToken}, Code: http.StatusOK}, + {Path: "/", Headers: map[string]string{"Authorization": validToken}, Code: http.StatusOK}, {Path: "/", Headers: map[string]string{"Authorization": "invalid_token"}, Code: http.StatusForbidden}, }...) }) t.Run("Form value", func(t *testing.T) { - bundleID := ts.RegisterBundle("id_extractor_form_value", pythonIDExtractorFormValue) - spec.CustomMiddlewareBundle = bundleID - spec.APIID = "api2" - - ts.Gw.LoadAPI(spec) - time.Sleep(1 * time.Second) + ts := gateway.StartTest(nil, gateway.TestConfig{ + CoprocessConfig: config.CoProcessConfig{ + EnableCoProcess: true, + PythonPathPrefix: pkgPath, + }, + }) + defer ts.Close() + + validToken := uuid.NewHex() + bundleID := ts.RegisterBundle("id_extractor_form_value", pythonIDExtractorFormValue(validToken)) + + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { + spec.Proxy.ListenPath = "/" + spec.UseKeylessAccess = false + spec.EnableCoProcessAuth = true + spec.CustomMiddlewareBundle = bundleID + spec.APIID = "api2" + }) formHeaders := map[string]string{"Content-Type": "application/x-www-form-urlencoded"} ts.Run(t, []test.TestCase{ - {Method: "POST", Path: "/", Headers: formHeaders, Data: url.Values{"auth": []string{"valid_token"}}.Encode(), Code: http.StatusOK}, - {Method: "POST", Path: "/", Headers: formHeaders, Data: url.Values{"auth": []string{"valid_token"}}.Encode(), Code: http.StatusOK}, + {Method: "POST", Path: "/", Headers: formHeaders, Data: url.Values{"auth": []string{validToken}}.Encode(), Code: http.StatusOK}, + {Method: "POST", Path: "/", Headers: formHeaders, Data: url.Values{"auth": []string{validToken}}.Encode(), Code: http.StatusOK}, {Method: "POST", Path: "/", Headers: formHeaders, Data: url.Values{"auth": []string{"invalid_token"}}.Encode(), Code: http.StatusForbidden}, }...) }) t.Run("Header regex", func(t *testing.T) { - bundleID := ts.RegisterBundle("id_extractor_header_regex", pythonIDExtractorHeaderRegex) - spec.CustomMiddlewareBundle = bundleID - spec.APIID = "api3" - - ts.Gw.LoadAPI(spec) - time.Sleep(1 * time.Second) + ts := gateway.StartTest(nil, gateway.TestConfig{ + CoprocessConfig: config.CoProcessConfig{ + EnableCoProcess: true, + PythonPathPrefix: pkgPath, + }, + }) + defer ts.Close() + + validToken := uuid.NewHex() + bundleID := ts.RegisterBundle("id_extractor_header_regex", pythonIDExtractorHeaderRegex(validToken)) + + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { + spec.Proxy.ListenPath = "/" + spec.UseKeylessAccess = false + spec.EnableCoProcessAuth = true + spec.CustomMiddlewareBundle = bundleID + spec.APIID = "api3" + }) ts.Run(t, []test.TestCase{ {Path: "/", Headers: map[string]string{"Authorization": "prefix-12345"}, Code: http.StatusOK}, diff --git a/coprocess/python/coprocess_python_test.go b/coprocess/python/coprocess_python_test.go index 2740d063fea..d1778b38e68 100644 --- a/coprocess/python/coprocess_python_test.go +++ b/coprocess/python/coprocess_python_test.go @@ -8,13 +8,13 @@ import ( "os" "path/filepath" "runtime" + "strings" "testing" - "time" "github.com/TykTechnologies/tyk/apidef" - "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/gateway" + "github.com/TykTechnologies/tyk/internal/uuid" "github.com/TykTechnologies/tyk/test" "github.com/TykTechnologies/tyk/user" ) @@ -26,21 +26,8 @@ func init() { pkgPath = filepath.Dir(filename) + "./../../" } -var pythonBundleWithAuthCheck = map[string]string{ - "manifest.json": ` - { - "file_list": [ - "middleware.py" - ], - "custom_middleware": { - "driver": "python", - "auth_check": { - "name": "MyAuthHook" - } - } - } -`, - "middleware.py": ` +var pythonBundleWithAuthCheck = func(token1, token2 string) map[string]string { + middleware := ` from tyk.decorators import * from gateway import TykGateway as tyk @@ -54,12 +41,32 @@ def MyAuthHook(request, session, metadata, spec): session.quota_max = 1 session.quota_renewal_rate = 60 metadata["token"] = "valid_token" - if auth_header == '47a0c79c427728b3df4af62b9228c8ae11': + if auth_header == 'token_without_quota': policy_id = request.get_header('Policy') session.apply_policy_id = policy_id - metadata["token"] = "47a0c79c427728b3df4af62b9228c8ae11" + metadata["token"] = "token_without_quota" return request, session, metadata +` + + middleware = strings.ReplaceAll(middleware, "valid_token", token1) + middleware = strings.ReplaceAll(middleware, "token_without_quota", token2) + + return map[string]string{ + "manifest.json": ` + { + "file_list": [ + "middleware.py" + ], + "custom_middleware": { + "driver": "python", + "auth_check": { + "name": "MyAuthHook" + } + } + } `, + "middleware.py": middleware, + } } var pythonBundleWithPostHook = map[string]string{ @@ -213,21 +220,26 @@ func TestMain(m *testing.M) { os.Exit(gateway.InitTestMain(context.Background(), m)) } -func TestPythonBundles(t *testing.T) { +func setupGateway() *gateway.Test { ts := gateway.StartTest(nil, gateway.TestConfig{ CoprocessConfig: config.CoProcessConfig{ EnableCoProcess: true, PythonPathPrefix: pkgPath, }}) - defer ts.Close() - authCheckBundle := ts.RegisterBundle("python_with_auth_check", pythonBundleWithAuthCheck) - postHookBundle := ts.RegisterBundle("python_with_post_hook", pythonBundleWithPostHook) - preHookBundle := ts.RegisterBundle("python_with_pre_hook", pythonBundleWithPreHook) - responseHookBundle := ts.RegisterBundle("python_with_response_hook", pythonBundleWithResponseHook) - postRequestTransformHookBundle := ts.RegisterBundle("python_post_with_request_transform_hook", pythonPostRequestTransform) + return ts +} + +func TestPythonBundles(t *testing.T) { + unused := uuid.NewHex() t.Run("Single-file bundle with authentication hook", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + validToken := uuid.NewHex() + authCheckBundle := ts.RegisterBundle("python_with_auth_check", pythonBundleWithAuthCheck(validToken, unused)) + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { spec.Proxy.ListenPath = "/test-api/" spec.UseKeylessAccess = false @@ -236,9 +248,7 @@ func TestPythonBundles(t *testing.T) { spec.VersionData.NotVersioned = true }) - time.Sleep(1 * time.Second) - - validAuth := map[string]string{"Authorization": "valid_token"} + validAuth := map[string]string{"Authorization": validToken} invalidAuth := map[string]string{"Authorization": "invalid_token"} ts.Run(t, []test.TestCase{ @@ -249,6 +259,12 @@ func TestPythonBundles(t *testing.T) { }) t.Run("Auth with policy", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + validToken := uuid.NewHex() + authCheckBundle := ts.RegisterBundle("python_with_auth_check", pythonBundleWithAuthCheck(unused, validToken)) + specs := ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { spec.Auth.AuthHeaderName = "Authorization" spec.Proxy.ListenPath = "/test-api/" @@ -258,8 +274,6 @@ func TestPythonBundles(t *testing.T) { spec.VersionData.NotVersioned = true }) - time.Sleep(1 * time.Second) - pID := ts.CreatePolicy(func(p *user.Policy) { p.QuotaMax = 1 p.QuotaRenewalRate = 60 @@ -267,9 +281,11 @@ func TestPythonBundles(t *testing.T) { APIID: specs[0].APIID, Versions: []string{"Default"}, }} + + t.Log(p.ID) }) - policyAuth := map[string]string{"authorization": "47a0c79c427728b3df4af62b9228c8ae11", "policy": pID} + policyAuth := map[string]string{"authorization": validToken, "policy": pID} ts.Run(t, []test.TestCase{ {Path: "/test-api/", Code: http.StatusOK, Headers: policyAuth}, @@ -278,6 +294,10 @@ func TestPythonBundles(t *testing.T) { }) t.Run("Single-file bundle with post hook", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + postHookBundle := ts.RegisterBundle("python_with_post_hook", pythonBundleWithPostHook) keyID := gateway.CreateSession(ts.Gw, func(s *user.SessionState) { s.MetaData = map[string]interface{}{ @@ -294,8 +314,6 @@ func TestPythonBundles(t *testing.T) { spec.VersionData.NotVersioned = true }) - time.Sleep(1 * time.Second) - auth := map[string]string{"Authorization": keyID} ts.Run(t, []test.TestCase{ @@ -304,6 +322,10 @@ func TestPythonBundles(t *testing.T) { }) t.Run("Single-file bundle with response hook", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + responseHookBundle := ts.RegisterBundle("python_with_response_hook", pythonBundleWithResponseHook) keyID := gateway.CreateSession(ts.Gw, func(s *user.SessionState) { s.MetaData = map[string]interface{}{ @@ -320,8 +342,6 @@ func TestPythonBundles(t *testing.T) { spec.VersionData.NotVersioned = true }) - time.Sleep(1 * time.Second) - auth := map[string]string{"Authorization": keyID} ts.Run(t, []test.TestCase{ @@ -330,6 +350,11 @@ func TestPythonBundles(t *testing.T) { }) t.Run("Single-file bundle with pre hook and UTF-8/non-UTF-8 request data", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + preHookBundle := ts.RegisterBundle("python_with_pre_hook", pythonBundleWithPreHook) + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { spec.Proxy.ListenPath = "/test-api-2/" spec.UseKeylessAccess = true @@ -338,8 +363,6 @@ func TestPythonBundles(t *testing.T) { spec.VersionData.NotVersioned = true }) - time.Sleep(1 * time.Second) - fileData := gateway.GenerateTestBinaryData() var buf bytes.Buffer multipartWriter := multipart.NewWriter(&buf) @@ -371,6 +394,11 @@ func TestPythonBundles(t *testing.T) { }) t.Run("python post hook with url rewrite and method transform", func(t *testing.T) { + ts := setupGateway() + defer ts.Close() + + postRequestTransformHookBundle := ts.RegisterBundle("python_post_with_request_transform_hook", pythonPostRequestTransform) + ts.Gw.BuildAndLoadAPI(func(spec *gateway.APISpec) { spec.Proxy.ListenPath = "/test-api-1/" spec.UseKeylessAccess = true @@ -402,8 +430,6 @@ func TestPythonBundles(t *testing.T) { spec.UseKeylessAccess = true }) - time.Sleep(1 * time.Second) - ts.Run(t, []test.TestCase{ {Path: "/test-api-1/get", Code: http.StatusOK, BodyMatch: "newpath"}, {Path: "/test-api-1/get", Code: http.StatusOK, BodyMatch: "GET"}, From 33d7294395065bf4c1a7b8e1d65d445f6903dc44 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Mon, 6 Nov 2023 11:46:42 +0100 Subject: [PATCH 18/33] [TT-10432] Mark test as flaky (#5738) Mark legacy graphql test as flaky to pass CI https://tyktech.atlassian.net/browse/TT-10432 Co-authored-by: Tit Petric --- apidef/adapter/graphql_config_adapter_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apidef/adapter/graphql_config_adapter_test.go b/apidef/adapter/graphql_config_adapter_test.go index f45bef32439..6e028bc4418 100644 --- a/apidef/adapter/graphql_config_adapter_test.go +++ b/apidef/adapter/graphql_config_adapter_test.go @@ -14,6 +14,7 @@ import ( "github.com/TykTechnologies/graphql-go-tools/pkg/engine/plan" "github.com/TykTechnologies/tyk/apidef" + "github.com/TykTechnologies/tyk/test" ) func TestGraphQLConfigAdapter_EngineConfigV2(t *testing.T) { @@ -458,6 +459,8 @@ func TestGraphQLConfigAdapter_engineConfigV2FieldConfigs(t *testing.T) { } func TestGraphQLConfigAdapter_engineConfigV2DataSources(t *testing.T) { + test.Flaky(t) + httpClient := &http.Client{} expectedDataSources := []plan.DataSourceConfiguration{ From ac2b1c848fa8dbfea6aa6cb770aac8d20748abd1 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 13:49:22 +0300 Subject: [PATCH 19/33] Merging to release-4-lts: [TT-9327] Decoding the URL request first, before handling any additional logic (#5345) (#5736) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [TT-9327] Decoding the URL request first, before handling any additional logic (#5345) this path works: /payment-intents but this path doesn't: /payment%2Dintents Encoded URLs aren't being rewritten when URL rewrite is applied. One edge case scenario that could break backwards compatibility (as described by @buger ), is that users can rely on escaped characters, and try to match them from the the url rewrite rules. In order to accomodate that, we are running url rewrite middleware twice: - once on the raw path - if transformations are failing and the url contains encoded characters, then we run it second time, with decoded URL ## Related Issue ## Motivation and Context ## How This Has Been Tested Unit test and manually ## Screenshots (if appropriate) ## Types of changes - [√ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why [TT-9327]: https://tyktech.atlassian.net/browse/TT-9327?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Laurentiu Ghiur Co-authored-by: Tit Petric --- gateway/mw_url_rewrite.go | 21 ++++++++++-- gateway/mw_url_rewrite_test.go | 18 +++++++--- gateway/util.go | 24 +++++++++++++ gateway/util_test.go | 62 ++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 7 deletions(-) diff --git a/gateway/mw_url_rewrite.go b/gateway/mw_url_rewrite.go index 78dce519b19..a4fae14302a 100644 --- a/gateway/mw_url_rewrite.go +++ b/gateway/mw_url_rewrite.go @@ -38,8 +38,18 @@ var envValueMatch = regexp.MustCompile(`\$secret_env.([A-Za-z0-9_\-\.]+)`) var metaMatch = regexp.MustCompile(`\$tyk_meta.([A-Za-z0-9_\-\.]+)`) var secretsConfMatch = regexp.MustCompile(`\$secret_conf.([A-Za-z0-9[.\-\_]+)`) -func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request) (string, error) { - path := r.URL.String() +func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request, decodeURL bool) (string, error) { + rawPath := r.URL.String() + path := rawPath + + if decodeURL { + var err error + path, err = url.PathUnescape(rawPath) + if err != nil { + return rawPath, fmt.Errorf("failed to decode URL path: %s", rawPath) + } + } + log.Debug("Inbound path: ", path) newpath := path @@ -196,6 +206,10 @@ func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request) (str newpath = gw.replaceTykVariables(r, newpath, true) + if rawPath == newpath && containsEscapedChars(rawPath) { + newpath, _ = gw.urlRewrite(meta, r, true) + } + return newpath, nil } @@ -478,7 +492,8 @@ func (m *URLRewriteMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Req umeta := meta.(*apidef.URLRewriteMeta) log.Debug(r.URL) oldPath := r.URL.String() - p, err := m.Gw.urlRewrite(umeta, r) + + p, err := m.Gw.urlRewrite(umeta, r, false) if err != nil { log.Error(err) return err, http.StatusInternalServerError diff --git a/gateway/mw_url_rewrite_test.go b/gateway/mw_url_rewrite_test.go index 0b93d619256..7b7bc45afc2 100644 --- a/gateway/mw_url_rewrite_test.go +++ b/gateway/mw_url_rewrite_test.go @@ -19,6 +19,16 @@ var testRewriterData = []struct { pattern, to string in, want string }{ + { + "Encoded", + "/test/payment-intents", "/change/to/me", + "/test/payment%2Dintents", "/change/to/me", + }, + { + "MatchEncodedChars", + "^(.+)%2[Dd](.+)$", "/change/to/me", + "/test/payment%2Dintents", "/change/to/me", + }, { "Straight", "/test/straight/rewrite", "/change/to/me", @@ -95,7 +105,7 @@ func TestRewriter(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { r := tc.reqMaker() - got, err := ts.Gw.urlRewrite(tc.meta, r) + got, err := ts.Gw.urlRewrite(tc.meta, r, false) if err != nil { t.Error("compile failed:", err) } @@ -113,7 +123,7 @@ func BenchmarkRewriter(b *testing.B) { //warm-up regexp caches for _, tc := range cases { r := tc.reqMaker() - ts.Gw.urlRewrite(tc.meta, r) + ts.Gw.urlRewrite(tc.meta, r, false) } b.ReportAllocs() @@ -123,7 +133,7 @@ func BenchmarkRewriter(b *testing.B) { b.StopTimer() r := tc.reqMaker() b.StartTimer() - ts.Gw.urlRewrite(tc.meta, r) + ts.Gw.urlRewrite(tc.meta, r, false) } } } @@ -1081,7 +1091,7 @@ func TestRewriterTriggers(t *testing.T) { Triggers: tc.triggerConf, } - got, err := ts.Gw.urlRewrite(&testConf, tc.req) + got, err := ts.Gw.urlRewrite(&testConf, tc.req, false) if err != nil { t.Error("compile failed:", err) } diff --git a/gateway/util.go b/gateway/util.go index 63e38685289..4d7d7871123 100644 --- a/gateway/util.go +++ b/gateway/util.go @@ -2,6 +2,7 @@ package gateway import ( "errors" + "net/url" "os" "github.com/TykTechnologies/tyk/apidef" @@ -158,3 +159,26 @@ func shouldReloadSpec(existingSpec, newSpec *APISpec) bool { return false } + +// check if 2 maps are the same +func areMapsEqual(a, b map[string]string) bool { + if len(a) != len(b) { + return false + } + for k, v := range a { + if b[k] != v { + return false + } + } + return true +} + +// checks if a string contains escaped characters +func containsEscapedChars(str string) bool { + unescaped, err := url.PathUnescape(str) + if err != nil { + return true + } + + return str != unescaped +} diff --git a/gateway/util_test.go b/gateway/util_test.go index 29ed9f07ceb..05d64daad07 100644 --- a/gateway/util_test.go +++ b/gateway/util_test.go @@ -215,3 +215,65 @@ func Test_shouldReloadSpec(t *testing.T) { assertionHelper(t, tcs) }) } + +func TestAreMapsEqual(t *testing.T) { + tests := []struct { + name string + map1 map[string]string + map2 map[string]string + expected bool + }{ + { + name: "Equal maps", + map1: map[string]string{"key1": "value1", "key2": "value2"}, + map2: map[string]string{"key1": "value1", "key2": "value2"}, + expected: true, + }, + { + name: "Different maps", + map1: map[string]string{"key1": "value1", "key2": "value2"}, + map2: map[string]string{"key1": "value1", "key2": "value3"}, + expected: false, + }, + { + name: "Different sizes", + map1: map[string]string{"key1": "value1", "key2": "value2", "key3": "value3"}, + map2: map[string]string{"key1": "value1", "key2": "value2"}, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := areMapsEqual(test.map1, test.map2) + if result != test.expected { + t.Errorf("areMapsEqual() = %v, want %v", result, test.expected) + } + }) + } +} + +func TestContainsEscapedCharacters(t *testing.T) { + tests := []struct { + value string + expected bool + }{ + { + value: "payment%2Dintents", + expected: true, + }, + { + value: "payment-intents", + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.value, func(t *testing.T) { + result := containsEscapedChars(test.value) + if result != test.expected { + t.Errorf("containsEscapedChars() = %v, want %v", result, test.expected) + } + }) + } +} From e48c51011c52362f770f6663eecd3aa43316322e Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 14:27:40 +0300 Subject: [PATCH 20/33] Merging to release-4-lts: [TT-9761] Add reload interval (#5418) (#5739) [TT-9761] Add reload interval (#5418) Add ability to manage the reload interval to take the load off the gateway ## Description ## Related Issue ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --------- Co-authored-by: Tit Petric Co-authored-by: Tit Petric [TT-9761]: https://tyktech.atlassian.net/browse/TT-9761?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Zaid Albirawi Co-authored-by: Tit Petric --- cli/linter/schema.json | 3 +++ config/config.go | 4 ++++ gateway/server.go | 10 ++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cli/linter/schema.json b/cli/linter/schema.json index 9f34d515c34..0150a801f8d 100644 --- a/cli/linter/schema.json +++ b/cli/linter/schema.json @@ -432,6 +432,9 @@ "hash_keys": { "type": "boolean" }, + "reload_interval": { + "type": "integer" + }, "hash_key_function": { "type": "string", "enum": [ diff --git a/config/config.go b/config/config.go index a124ff03afa..6b461d1f373 100644 --- a/config/config.go +++ b/config/config.go @@ -609,6 +609,10 @@ type Config struct { // Disable dynamic API and Policy reloads, e.g. it will load new changes only on procecss start. SuppressRedisSignalReload bool `json:"suppress_redis_signal_reload"` + // ReloadInterval defines a duration in seconds within which the gateway responds to a reload event. + // The value defaults to 1, values lower than 1 are ignored. + ReloadInterval int64 `json:"reload_interval"` + // Enable Key hashing HashKeys bool `json:"hash_keys"` diff --git a/gateway/server.go b/gateway/server.go index a0b790c2548..d5f227a8c84 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -1560,7 +1560,8 @@ func (gw *Gateway) start() { go gw.startPubSubLoop() } - if slaveOptions := gw.GetConfig().SlaveOptions; slaveOptions.UseRPC { + conf := gw.GetConfig() + if slaveOptions := conf.SlaveOptions; slaveOptions.UseRPC { mainLog.Debug("Starting RPC reload listener") gw.RPCListener = RPCStorageHandler{ KeyPrefix: "rpc.listener.", @@ -1574,9 +1575,14 @@ func (gw *Gateway) start() { go gw.RPCListener.StartRPCLoopCheck(slaveOptions.RPCKey) } + reloadInterval := time.Second + if conf.ReloadInterval > 0 { + reloadInterval = time.Duration(conf.ReloadInterval) * time.Second + } + // 1s is the minimum amount of time between hot reloads. The // interval counts from the start of one reload to the next. - go gw.reloadLoop(time.Tick(time.Second)) + go gw.reloadLoop(time.Tick(reloadInterval)) go gw.reloadQueueLoop() } From 2a9c684fc2f6c4fbd4d253a531e9ac505e3610c3 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 14:54:12 +0300 Subject: [PATCH 21/33] Merging to release-4-lts: [TT-9284] Ensure that old transport will close idle connections (#5231) (#5741) [TT-9284] Ensure that old transport will close idle connections (#5231)

Summary [CS] The gateway leaks file handles via sockets when max_conn_time is above 0
Type Bug Bug
Status In Code Review
Points N/A
--- TBD ## Description ## Related Issue ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --------- Co-authored-by: Tit Petric [TT-9284]: https://tyktech.atlassian.net/browse/TT-9284?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Tit Petric --- gateway/proxy_muxer.go | 3 ++ gateway/reverse_proxy.go | 15 ++++++++ gateway/reverse_proxy_test.go | 16 ++++++-- gateway/server.go | 3 ++ gateway/testutil.go | 5 ++- internal/httputil/connection_watcher.go | 40 ++++++++++++++++++++ internal/httputil/connection_watcher_test.go | 28 ++++++++++++++ 7 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 internal/httputil/connection_watcher.go create mode 100644 internal/httputil/connection_watcher_test.go diff --git a/gateway/proxy_muxer.go b/gateway/proxy_muxer.go index 1065061b1fa..a84e1c7ff83 100644 --- a/gateway/proxy_muxer.go +++ b/gateway/proxy_muxer.go @@ -428,6 +428,9 @@ func (m *proxyMux) serve(gw *Gateway) { WriteTimeout: writeTimeout, Handler: h, } + if gw.ConnectionWatcher != nil { + p.httpServer.ConnState = gw.ConnectionWatcher.OnStateChange + } if conf.CloseConnections { p.httpServer.SetKeepAlivesEnabled(false) diff --git a/gateway/reverse_proxy.go b/gateway/reverse_proxy.go index 468e0ffb096..7eccdb4c372 100644 --- a/gateway/reverse_proxy.go +++ b/gateway/reverse_proxy.go @@ -392,6 +392,8 @@ type ReverseProxy struct { Gw *Gateway `json:"-"` } +var idleConnTimeout = 90 + func (p *ReverseProxy) defaultTransport(dialerTimeout float64) *http.Transport { timeout := 30.0 if dialerTimeout > 0 { @@ -413,6 +415,7 @@ func (p *ReverseProxy) defaultTransport(dialerTimeout float64) *http.Transport { DialContext: dialContextFunc, MaxIdleConns: p.Gw.GetConfig().MaxIdleConns, MaxIdleConnsPerHost: p.Gw.GetConfig().MaxIdleConnsPerHost, // default is 100 + IdleConnTimeout: time.Duration(idleConnTimeout) * time.Second, ResponseHeaderTimeout: time.Duration(dialerTimeout) * time.Second, TLSHandshakeTimeout: 10 * time.Second, } @@ -1274,9 +1277,21 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques } if createTransport { + var oldTransport *http.Transport + + if p.TykAPISpec.HTTPTransport != nil { + oldTransport = p.TykAPISpec.HTTPTransport.transport + // Prevent new idle connections to be generated. + oldTransport.DisableKeepAlives = true + } + _, timeout := p.CheckHardTimeoutEnforced(p.TykAPISpec, req) p.TykAPISpec.HTTPTransport = p.httpTransport(timeout, rw, req, outreq) p.TykAPISpec.HTTPTransportCreated = time.Now() + + if oldTransport != nil { + oldTransport.CloseIdleConnections() + } } roundTripper = p.TykAPISpec.HTTPTransport diff --git a/gateway/reverse_proxy_test.go b/gateway/reverse_proxy_test.go index 6c2b3c91ca8..bd244cfc5e4 100644 --- a/gateway/reverse_proxy_test.go +++ b/gateway/reverse_proxy_test.go @@ -369,13 +369,21 @@ func (s *Test) TestNewWrappedServeHTTP() *ReverseProxy { } func TestWrappedServeHTTP(t *testing.T) { + idleConnTimeout = 1 + ts := StartTest(nil) defer ts.Close() - proxy := ts.TestNewWrappedServeHTTP() - recorder := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodGet, "/", nil) - proxy.WrappedServeHTTP(recorder, req, false) + for i := 0; i < 10; i++ { + proxy := ts.TestNewWrappedServeHTTP() + recorder := httptest.NewRecorder() + req, _ := http.NewRequest(http.MethodGet, "/", nil) + proxy.WrappedServeHTTP(recorder, req, false) + } + + assert.Equal(t, 10, ts.Gw.ConnectionWatcher.Count()) + time.Sleep(time.Second * 2) + assert.Equal(t, 0, ts.Gw.ConnectionWatcher.Count()) } func TestCircuitBreaker5xxs(t *testing.T) { diff --git a/gateway/server.go b/gateway/server.go index d5f227a8c84..6a70607623f 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -21,6 +21,7 @@ import ( "sync" "github.com/TykTechnologies/tyk/internal/crypto" + "github.com/TykTechnologies/tyk/internal/httputil" "sync/atomic" textTemplate "text/template" @@ -109,6 +110,7 @@ type Gateway struct { DashService DashboardServiceSender CertificateManager *certs.CertificateManager GlobalHostChecker HostCheckerManager + ConnectionWatcher *httputil.ConnectionWatcher HostCheckTicker chan struct{} HostCheckerClient *http.Client @@ -213,6 +215,7 @@ func NewGateway(config config.Config, ctx context.Context, cancelFn context.Canc gw.HostCheckerClient = &http.Client{ Timeout: 500 * time.Millisecond, } + gw.ConnectionWatcher = httputil.NewConnectionWatcher() gw.SessionCache = cache.New(10*time.Second, 5*time.Second) gw.ExpiryCache = cache.New(600*time.Second, 10*time.Minute) diff --git a/gateway/testutil.go b/gateway/testutil.go index 56a3c7cbab5..eb40da0d982 100644 --- a/gateway/testutil.go +++ b/gateway/testutil.go @@ -33,6 +33,7 @@ import ( "github.com/gorilla/websocket" "golang.org/x/net/context" + "github.com/TykTechnologies/tyk/internal/httputil" "github.com/TykTechnologies/tyk/internal/uuid" "github.com/TykTechnologies/graphql-go-tools/pkg/execution/datasource" @@ -1018,10 +1019,9 @@ func (s *Test) BootstrapGw(ctx context.Context, cancelFn context.CancelFunc, gen } gwConfig.CoProcessOptions = s.config.CoprocessConfig - s.gwMu.Lock() s.Gw = NewGateway(gwConfig, ctx, cancelFn) s.Gw.setTestMode(true) - s.gwMu.Unlock() + s.Gw.ConnectionWatcher = httputil.NewConnectionWatcher() s.MockHandle = MockHandle @@ -1067,6 +1067,7 @@ func (s *Test) BootstrapGw(ctx context.Context, cancelFn context.CancelFunc, gen Handler: s.TestServerRouter, ReadTimeout: 1 * time.Second, WriteTimeout: 1 * time.Second, + ConnState: s.Gw.ConnectionWatcher.OnStateChange, MaxHeaderBytes: 1 << 20, } diff --git a/internal/httputil/connection_watcher.go b/internal/httputil/connection_watcher.go new file mode 100644 index 00000000000..57250605786 --- /dev/null +++ b/internal/httputil/connection_watcher.go @@ -0,0 +1,40 @@ +package httputil + +import ( + "net" + "net/http" + "sync/atomic" +) + +// ConnectionWatcher counts http server connections. +type ConnectionWatcher struct { + n int64 +} + +// NewConnectionWatcher returns a new *ConnectionWatcher. +func NewConnectionWatcher() *ConnectionWatcher { + return &ConnectionWatcher{} +} + +// OnStateChange records open connections in response to connection +// state changes. Set net/http Server.ConnState to this method +// as value. +func (cw *ConnectionWatcher) OnStateChange(_ net.Conn, state http.ConnState) { + switch state { + case http.StateNew: + cw.Add(1) + case http.StateHijacked, http.StateClosed: + cw.Add(-1) + } +} + +// Count returns the number of connections at the time the call. + +func (cw *ConnectionWatcher) Count() int { + return int(atomic.LoadInt64(&cw.n)) +} + +// Add adds c to the number of active connections. +func (cw *ConnectionWatcher) Add(c int64) { + atomic.AddInt64(&cw.n, c) +} diff --git a/internal/httputil/connection_watcher_test.go b/internal/httputil/connection_watcher_test.go new file mode 100644 index 00000000000..37a9c3ce50e --- /dev/null +++ b/internal/httputil/connection_watcher_test.go @@ -0,0 +1,28 @@ +package httputil_test + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/TykTechnologies/tyk/internal/httputil" +) + +func TestConnectionWatcher(t *testing.T) { + w := httputil.NewConnectionWatcher() + w.Add(1) + assert.Equal(t, 1, w.Count()) + w.Add(2) + assert.Equal(t, 3, w.Count()) + w.Add(-3) + assert.Equal(t, 0, w.Count()) + + w.OnStateChange(nil, http.StateNew) + assert.Equal(t, 1, w.Count()) + + w.OnStateChange(nil, http.StateClosed) + w.OnStateChange(nil, http.StateHijacked) + assert.Equal(t, -1, w.Count()) + +} From 64965de94931ef93e9b526c5a84ce83300f1dc49 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Mon, 6 Nov 2023 15:20:37 +0300 Subject: [PATCH 22/33] Merging to release-4-lts: [TT-9924]remove muxer, proxy from explicitRouteHandler (#5482) (#5733) [TT-9924]remove muxer, proxy from explicitRouteHandler (#5482) Remove muxer from explicitRouteHandler [TT-9924]: https://tyktech.atlassian.net/browse/TT-9924?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Jeffy Mathew Co-authored-by: Tit Petric --- gateway/api_loader.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gateway/api_loader.go b/gateway/api_loader.go index 5e61e3a1a59..c0263e179cc 100644 --- a/gateway/api_loader.go +++ b/gateway/api_loader.go @@ -671,7 +671,6 @@ func (gw *Gateway) fuzzyFindAPI(search string) *APISpec { type explicitRouteHandler struct { prefix string handler http.Handler - muxer *proxyMux } func (h *explicitRouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -679,10 +678,12 @@ func (h *explicitRouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) h.handler.ServeHTTP(w, r) return } - h.muxer.handle404(w, r) + + w.WriteHeader(http.StatusNotFound) + _, _ = fmt.Fprint(w, http.StatusText(http.StatusNotFound)) } -func explicitRouteSubpaths(prefix string, handler http.Handler, muxer *proxyMux, enabled bool) http.Handler { +func explicitRouteSubpaths(prefix string, handler http.Handler, enabled bool) http.Handler { // feature is enabled via config option if !enabled { return handler @@ -700,7 +701,6 @@ func explicitRouteSubpaths(prefix string, handler http.Handler, muxer *proxyMux, return &explicitRouteHandler{ prefix: prefix, handler: handler, - muxer: muxer, } } @@ -761,7 +761,7 @@ func (gw *Gateway) loadHTTPService(spec *APISpec, apisByListen map[string]int, g subrouter.Handle(rateLimitEndpoint, chainObj.RateLimitChain) } - httpHandler := explicitRouteSubpaths(prefix, chainObj.ThisHandler, muxer, gwConfig.HttpServerOptions.EnableStrictRoutes) + httpHandler := explicitRouteSubpaths(prefix, chainObj.ThisHandler, gwConfig.HttpServerOptions.EnableStrictRoutes) // Attach handlers subrouter.NewRoute().Handler(httpHandler) From 00d326e3a3521633016c49613b9b2e79d8f172ae Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 10:14:47 +0300 Subject: [PATCH 23/33] Merging to release-4-lts: TT-8942 Change default RPC pool size (#5030) TT-8942 Change default RPC pool size (#5030) ## Description Default RPC pool size is set to 20 and because of the relatively heavy CPU and Memory footprint of the RPC connections in the MDCB model this can cause issues where either the gateways or MDCB fail on load cause by scaling events or component failure at MDCB side. ## Related Issue https://tyktech.atlassian.net/browse/TT-8942 ## Motivation and Context https://tyktech.atlassian.net/browse/TT-8942 ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --- config/config.go | 2 +- rpc/rpc_client.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 6b461d1f373..135e2bf713a 100644 --- a/config/config.go +++ b/config/config.go @@ -308,7 +308,7 @@ type SlaveOptionsConfig struct { // The maximum time in seconds that a RPC ping can last. PingTimeout int `json:"ping_timeout"` - // The number of RPC connections in the pool. Basically it creates a set of connections that you can re-use as needed. + // The number of RPC connections in the pool. Basically it creates a set of connections that you can re-use as needed. Defaults to 5. RPCPoolSize int `json:"rpc_pool_size"` // You can use this to set a period for which the Gateway will check if there are changes in keys that must be synchronized. If this value is not set then it will default to 10 seconds. diff --git a/rpc/rpc_client.go b/rpc/rpc_client.go index 351aa82559f..e9099689b85 100644 --- a/rpc/rpc_client.go +++ b/rpc/rpc_client.go @@ -250,7 +250,7 @@ func Connect(connConfig Config, suppressRegister bool, dispatcherFuncs map[strin clientSingleton.Conns = values.Config().RPCPoolSize if clientSingleton.Conns == 0 { - clientSingleton.Conns = 20 + clientSingleton.Conns = 5 } clientSingleton.Dial = func(addr string) (conn net.Conn, err error) { From 7dd58742ae5ef00778ec1184e1924d7ef05c6a8d Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 10:43:56 +0300 Subject: [PATCH 24/33] Merging to release-4-lts: TT-8934 Fix chunked response analytics (#5495) (#5746) TT-8934 Fix chunked response analytics (#5495) ## Description When transfer-encoding is chunked on the upstream response, analytics records raw responses also contain the chunked characters (example https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding#examples). This is not expected. The proposed solution is to delete the transfer-encoding header before reading and writing the response body to the rawResponse field. Without this header, Go will process the header as it should. ## Related Issue https://tyktech.atlassian.net/browse/TT-8934 ## Motivation and Context https://tyktech.atlassian.net/browse/TT-8934 ## How This Has Been Tested Added tests ## Screenshots (if appropriate) ## Types of changes - [X] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --------- Co-authored-by: Tomas Buchaillot Co-authored-by: Tit Petric --- gateway/handler_success.go | 5 +++ internal/httputil/response.go | 33 ++++++++++++++ internal/httputil/response_test.go | 72 ++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 internal/httputil/response.go create mode 100644 internal/httputil/response_test.go diff --git a/gateway/handler_success.go b/gateway/handler_success.go index 1e6d6b44fb8..6dfadbb68bf 100644 --- a/gateway/handler_success.go +++ b/gateway/handler_success.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/TykTechnologies/tyk/internal/httputil" + "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/ctx" "github.com/TykTechnologies/tyk/headers" @@ -170,6 +172,9 @@ func (s *SuccessHandler) RecordHit(r *http.Request, timing Latency, code int, re // mw_redis_cache instead? is there a reason not // to include that in the analytics? if responseCopy != nil { + // we need to delete the chunked transfer encoding header to avoid malformed body in our rawResponse + httputil.RemoveResponseTransferEncoding(responseCopy, "chunked") + contents, err := ioutil.ReadAll(responseCopy.Body) if err != nil { log.Error("Couldn't read response body", err) diff --git a/internal/httputil/response.go b/internal/httputil/response.go new file mode 100644 index 00000000000..26e7fff1466 --- /dev/null +++ b/internal/httputil/response.go @@ -0,0 +1,33 @@ +package httputil + +import ( + "net/http" +) + +// EntityTooLarge responds with HTTP 413 Request Entity Too Large. +// The function is used for a response when blocking requests by size. +func EntityTooLarge(w http.ResponseWriter, _ *http.Request) { + status := http.StatusRequestEntityTooLarge + http.Error(w, http.StatusText(status), status) +} + +// LengthRequired responds with HTTP 411 Length Required. +// The function is used in places where Content-Length is required. +func LengthRequired(w http.ResponseWriter, _ *http.Request) { + status := http.StatusLengthRequired + http.Error(w, http.StatusText(status), status) +} + +// InternalServerError responds with HTTP 503 Internal Server Error. +func InternalServerError(w http.ResponseWriter, _ *http.Request) { + status := http.StatusInternalServerError + http.Error(w, http.StatusText(status), status) +} + +func RemoveResponseTransferEncoding(response *http.Response, encoding string) { + for i, value := range response.TransferEncoding { + if value == encoding { + response.TransferEncoding = append(response.TransferEncoding[:i], response.TransferEncoding[i+1:]...) + } + } +} diff --git a/internal/httputil/response_test.go b/internal/httputil/response_test.go new file mode 100644 index 00000000000..6efea65b025 --- /dev/null +++ b/internal/httputil/response_test.go @@ -0,0 +1,72 @@ +package httputil + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRequestUtilities(t *testing.T) { + w := httptest.NewRecorder() + EntityTooLarge(w, nil) + assert.Equal(t, http.StatusRequestEntityTooLarge, w.Result().StatusCode) + + w = httptest.NewRecorder() + LengthRequired(w, nil) + assert.Equal(t, http.StatusLengthRequired, w.Result().StatusCode) + + w = httptest.NewRecorder() + InternalServerError(w, nil) + assert.Equal(t, http.StatusInternalServerError, w.Result().StatusCode) +} + +func TestRemoveResponseTransferEncoding(t *testing.T) { + tests := []struct { + name string + response *http.Response + encoding string + expectedOutput []string + }{ + { + name: "Remove chunked encoding", + response: &http.Response{ + TransferEncoding: []string{"chunked", "gzip"}, + }, + encoding: "chunked", + expectedOutput: []string{"gzip"}, + }, + { + name: "Remove gzip encoding", + response: &http.Response{ + TransferEncoding: []string{"chunked", "gzip"}, + }, + encoding: "gzip", + expectedOutput: []string{"chunked"}, + }, + { + name: "Remove non-existent encoding", + response: &http.Response{ + TransferEncoding: []string{"chunked", "gzip"}, + }, + encoding: "deflate", + expectedOutput: []string{"chunked", "gzip"}, + }, + { + name: "Remove from empty slice", + response: &http.Response{ + TransferEncoding: []string{}, + }, + encoding: "gzip", + expectedOutput: []string{}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + RemoveResponseTransferEncoding(tc.response, tc.encoding) + assert.Equal(t, tc.expectedOutput, tc.response.TransferEncoding) + }) + } +} From 512f31ee83fdcaa1b0249de4651f2602819a6a1e Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 10:48:01 +0300 Subject: [PATCH 25/33] Merging to release-4-lts: [TT-8558] Do not stop applying polices when one of them non-existing (#5124) [TT-8558] Do not stop applying polices when one of them non-existing (#5124) In multiple policies applied to a key case, if one of the policies is not found, the other policies should continue to be applied so that their APIs continues to work. --- gateway/middleware.go | 4 ++++ gateway/policy_test.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/gateway/middleware.go b/gateway/middleware.go index 88d541f459d..d40d7b5c796 100644 --- a/gateway/middleware.go +++ b/gateway/middleware.go @@ -327,6 +327,10 @@ func (t BaseMiddleware) ApplyPolicies(session *user.SessionState) error { if !ok { err := fmt.Errorf("policy not found: %q", polID) t.Logger().Error(err) + if len(policies) > 1 { + continue + } + return err } // Check ownership, policy org owner must be the same as API, diff --git a/gateway/policy_test.go b/gateway/policy_test.go index bce0f2bab30..d32562a1038 100644 --- a/gateway/policy_test.go +++ b/gateway/policy_test.go @@ -377,7 +377,7 @@ func (s *Test) TestPrepareApplyPolicies() (*BaseMiddleware, []testApplyPoliciesD }, { name: "MultiNonPart", - policies: []string{"nonpart1", "nonpart2"}, + policies: []string{"nonpart1", "nonpart2", "nonexistent"}, sessMatch: func(t *testing.T, s *user.SessionState) { want := map[string]user.AccessDefinition{ "a": { From f83b98f0410f0d78c02344d295712ae9cb9d08c2 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 11:09:45 +0300 Subject: [PATCH 26/33] Merging to release-4-lts: [TT-926] fix security vulnerability that exposes key in the log (#5080) [TT-926] fix security vulnerability that exposes key in the log (#5080) ## Description The problem involved the HashKey function in [storage.go](https://github.com/TykTechnologies/tyk/blob/76a00611f33e150b1b6145264909baeefa1cbd4f/storage/storage.go#L170). It returns the key without hashing if "hash_keys" is set to false in the tyk.conf file. Now a conditional has been added that obfuscates the key if "hash_keys" and "enable_key_logging" are set to false. ## Related Issue [View issue here](https://tyktech.atlassian.net/browse/TT-926) ## Motivation and Context This issue is a low level security vulnerability. ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --- gateway/auth_manager.go | 11 +++++++++-- gateway/auth_manager_test.go | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/gateway/auth_manager.go b/gateway/auth_manager.go index 0a56ad39ceb..88a04511e93 100644 --- a/gateway/auth_manager.go +++ b/gateway/auth_manager.go @@ -33,6 +33,13 @@ type DefaultSessionManager struct { Gw *Gateway `json:"-"` } +func (b *DefaultSessionManager) ResetQuotaObfuscateKey(keyName string) string { + if !b.Gw.GetConfig().HashKeys && !b.Gw.GetConfig().EnableKeyLogging { + return b.Gw.obfuscateKey(keyName) + } + return keyName +} + func (b *DefaultSessionManager) Init(store storage.Handler) { b.store = store b.store.Connect() @@ -52,6 +59,7 @@ func (b *DefaultSessionManager) Store() storage.Handler { func (b *DefaultSessionManager) ResetQuota(keyName string, session *user.SessionState, isHashed bool) { origKeyName := keyName + if !isHashed { keyName = storage.HashKey(keyName, b.Gw.GetConfig().HashKeys) } @@ -60,7 +68,7 @@ func (b *DefaultSessionManager) ResetQuota(keyName string, session *user.Session log.WithFields(logrus.Fields{ "prefix": "auth-mgr", "inbound-key": b.Gw.obfuscateKey(origKeyName), - "key": rawKey, + "key": b.ResetQuotaObfuscateKey(keyName), }).Info("Reset quota for key.") rateLimiterSentinelKey := RateLimitKeyPrefix + keyName + ".BLOCKED" @@ -81,7 +89,6 @@ func (b *DefaultSessionManager) clearCacheForKey(keyName string, hashed bool) { if !hashed { cacheKey = storage.HashKey(keyName, b.Gw.GetConfig().HashKeys) } - // Delete gateway's cache immediately b.Gw.SessionCache.Delete(cacheKey) diff --git a/gateway/auth_manager_test.go b/gateway/auth_manager_test.go index 97620acf1a3..da673e03db2 100644 --- a/gateway/auth_manager_test.go +++ b/gateway/auth_manager_test.go @@ -5,6 +5,8 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/TykTechnologies/tyk/certs" "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/headers" @@ -245,3 +247,39 @@ func TestHashKeyFunctionChanged(t *testing.T) { }) } + +func TestResetQuotaObfuscate(t *testing.T) { + + t.Run("Obfuscate key", func(t *testing.T) { + conf := func(globalConf *config.Config) { + globalConf.HashKeys = false + globalConf.EnableKeyLogging = false + } + + ts := StartTest(conf) + sessionManager := DefaultSessionManager{Gw: ts.Gw} + t.Cleanup(func() { + ts.Close() + }) + + actual := sessionManager.ResetQuotaObfuscateKey("481408ygjkbs") + + assert.Equal(t, "****jkbs", actual) + }) + t.Run("Does not Obfuscate key", func(t *testing.T) { + conf := func(globalConf *config.Config) { + globalConf.HashKeys = true + globalConf.EnableKeyLogging = true + } + + ts := StartTest(conf) + sessionManager := DefaultSessionManager{Gw: ts.Gw} + t.Cleanup(func() { + ts.Close() + }) + + actual := sessionManager.ResetQuotaObfuscateKey("481408ygjkbs") + + assert.Equal(t, "481408ygjkbs", actual) + }) +} From cb8d30645618a4d37b79d3c3a9c87be069ff433b Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 11:14:12 +0300 Subject: [PATCH 27/33] Merging to release-4-lts: [TT-9829] Fix checking json.Marshal errors in tests (#5426) (#5751) [TT-9829] Fix checking json.Marshal errors in tests (#5426) - Added `test.MarshalJSON` utility for encoding json in tests and asserting the error return is nil, - Updated usage in tests This is required to resolve some sonarcloud errors in existing tests code. https://tyktech.atlassian.net/browse/TT-9829 --------- Co-authored-by: Tit Petric [TT-9829]: https://tyktech.atlassian.net/browse/TT-9829?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Tit Petric Co-authored-by: Tit Petric --- gateway/api_test.go | 42 +++++++++---------- gateway/gateway_test.go | 2 +- ..._test.go => grpc_streaming_client_test.go} | 5 ++- gateway/oauth_manager_test.go | 2 +- gateway/testutil.go | 5 +-- test/json.go | 20 +++++++++ test/json_test.go | 14 +++++++ 7 files changed, 61 insertions(+), 29 deletions(-) rename gateway/{grpc_streamin_client_test.go => grpc_streaming_client_test.go} (99%) create mode 100644 test/json.go create mode 100644 test/json_test.go diff --git a/gateway/api_test.go b/gateway/api_test.go index 66960b78d40..a75fcaaf64b 100644 --- a/gateway/api_test.go +++ b/gateway/api_test.go @@ -148,14 +148,14 @@ func TestKeyHandler(t *testing.T) { // Access right not specified masterKey := CreateStandardSession() - masterKeyJSON, _ := json.Marshal(masterKey) + masterKeyJSON := test.MarshalJSON(t)(masterKey) //TestTykMakeHTTPRequest // with access withAccess := CreateStandardSession() withAccess.AccessRights = map[string]user.AccessDefinition{"test": { APIID: "test", Versions: []string{"v1"}, }} - withAccessJSON, _ := json.Marshal(withAccess) + withAccessJSON := test.MarshalJSON(t)(withAccess) // with policy ts.Gw.policiesMu.Lock() @@ -170,12 +170,12 @@ func TestKeyHandler(t *testing.T) { } ts.Gw.policiesMu.Unlock() withPolicy := CreateStandardSession() - withoutPolicyJSON, _ := json.Marshal(withPolicy) + withoutPolicyJSON := test.MarshalJSON(t)(withPolicy) withPolicy.ApplyPolicies = []string{ "abc_policy", } - withPolicyJSON, _ := json.Marshal(withPolicy) + withPolicyJSON := test.MarshalJSON(t)(withPolicy) // with invalid policy withBadPolicy := CreateStandardSession() @@ -185,7 +185,7 @@ func TestKeyHandler(t *testing.T) { withBadPolicy.ApplyPolicies = []string{ "xyz_policy", } - withBadPolicyJSON, _ := json.Marshal(withBadPolicy) + withBadPolicyJSON := test.MarshalJSON(t)(withBadPolicy) t.Run("Create key", func(t *testing.T) { ts.Run(t, []test.TestCase{ @@ -379,7 +379,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) { t.Run("Add policy not enforcing acl", func(t *testing.T) { session.ApplyPolicies = append(session.ApplyPolicies, pID2) - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -394,7 +394,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) { t.Run("Remove policy not enforcing acl", func(t *testing.T) { session.ApplyPolicies = []string{} - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -409,7 +409,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) { t.Run("Tags on key level", func(t *testing.T) { assertTags := func(session *user.SessionState, expected []string) { - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -450,7 +450,7 @@ func TestKeyHandler_UpdateKey(t *testing.T) { t.Run("MetaData on key level", func(t *testing.T) { assertMetaData := func(session *user.SessionState, expected map[string]interface{}) { - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -630,7 +630,7 @@ func TestUpdateKeyWithCert(t *testing.T) { }) session.Certificate = newCertID - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -653,7 +653,7 @@ func TestUpdateKeyWithCert(t *testing.T) { // attempt to set an empty cert session.Certificate = "" - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -675,7 +675,7 @@ func TestUpdateKeyWithCert(t *testing.T) { }) session.Certificate = "invalid-cert-id" - sessionData, _ := json.Marshal(session) + sessionData := test.MarshalJSON(t)(session) path := fmt.Sprintf("/tyk/keys/%s", key) _, _ = ts.Run(t, []test.TestCase{ @@ -752,7 +752,7 @@ func TestKeyHandler_CheckKeysNotDuplicateOnUpdate(t *testing.T) { t.Error("Failed to create key, ensure security settings are correct:" + err.Error()) } - requestByte, _ := json.Marshal(session) + requestByte := test.MarshalJSON(t)(session) r := httptest.NewRequest(http.MethodPut, "/tyk/keys/"+keyName, bytes.NewReader(requestByte)) ts.Gw.handleAddOrUpdate(keyName, r, tc.HashKeys) @@ -861,7 +861,7 @@ func (ts *Test) testHashKeyHandlerHelper(t *testing.T, expectedHashSize int) { withAccess.AccessRights = map[string]user.AccessDefinition{"test": { APIID: "test", Versions: []string{"v1"}, }} - withAccessJSON, _ := json.Marshal(withAccess) + withAccessJSON := test.MarshalJSON(t)(withAccess) myKey := "my_key_id" myKeyHash := storage.HashKey(ts.Gw.generateToken("default", myKey), ts.Gw.GetConfig().HashKeys) @@ -1029,7 +1029,7 @@ func TestHashKeyListingDisabled(t *testing.T) { withAccess.AccessRights = map[string]user.AccessDefinition{"test": { APIID: "test", Versions: []string{"v1"}, }} - withAccessJSON, _ := json.Marshal(withAccess) + withAccessJSON := test.MarshalJSON(t)(withAccess) myKey := "my_key_id" myKeyHash := storage.HashKey(ts.Gw.generateToken("default", myKey), ts.Gw.GetConfig().HashKeys) @@ -1145,7 +1145,7 @@ func TestKeyHandler_HashingDisabled(t *testing.T) { withAccess.AccessRights = map[string]user.AccessDefinition{"test": { APIID: "test", Versions: []string{"v1"}, }} - withAccessJSON, _ := json.Marshal(withAccess) + withAccessJSON := test.MarshalJSON(t)(withAccess) myKeyID := "my_key_id" token := ts.Gw.generateToken("default", myKeyID) @@ -1238,7 +1238,7 @@ func TestGetOAuthClients(t *testing.T) { APIID: "test", ClientSecret: "secret", } - validOauthRequest, _ := json.Marshal(oauthRequest) + validOauthRequest := test.MarshalJSON(t)(oauthRequest) ts.Run(t, []test.TestCase{ {Path: "/tyk/oauth/clients/unknown", AdminAuth: true, Code: 404}, @@ -1343,8 +1343,8 @@ func TestCreateOAuthClient(t *testing.T) { for testName, testData := range tests { t.Run(testName, func(t *testing.T) { - requestData, _ := json.Marshal(testData.req) - ts.Run( + requestData := test.MarshalJSON(t)(testData.req) + _, _ = ts.Run( t, test.TestCase{ Method: http.MethodPost, @@ -1468,7 +1468,7 @@ func TestUpdateOauthClientHandler(t *testing.T) { for testName, testData := range tests { t.Run(testName, func(t *testing.T) { - requestData, _ := json.Marshal(testData.req) + requestData := test.MarshalJSON(t)(testData.req) testCase := test.TestCase{ Method: http.MethodPut, Path: "/tyk/oauth/clients/test/12345", @@ -1813,7 +1813,7 @@ func TestRotateClientSecretHandler(t *testing.T) { for testName, testData := range tests { t.Run(testName, func(t *testing.T) { - requestData, _ := json.Marshal(testData.req) + requestData := test.MarshalJSON(t)(testData.req) testCase := test.TestCase{ Method: http.MethodPut, Path: "/tyk/oauth/clients/test/12345/rotate", diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index 15b81dd4924..36fa2dc5c58 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -999,7 +999,7 @@ func TestManagementNodeRedisEvents(t *testing.T) { } n.Sign() msg := redis.Message{} - payload, _ := json.Marshal(n) + payload := test.MarshalJSON(t)(n) msg.Payload = string(payload) callbackRun := false diff --git a/gateway/grpc_streamin_client_test.go b/gateway/grpc_streaming_client_test.go similarity index 99% rename from gateway/grpc_streamin_client_test.go rename to gateway/grpc_streaming_client_test.go index 3cd2c7d98bf..2ded216b093 100644 --- a/gateway/grpc_streamin_client_test.go +++ b/gateway/grpc_streaming_client_test.go @@ -24,7 +24,6 @@ package gateway import ( "context" - "encoding/json" "io" "math/rand" "sync" @@ -33,6 +32,8 @@ import ( "google.golang.org/grpc" pb "google.golang.org/grpc/examples/route_guide/routeguide" + + "github.com/TykTechnologies/tyk/test" ) // printFeature gets the feature for the given point. @@ -71,7 +72,7 @@ func printFeatures(t *testing.T, client pb.RouteGuideClient, rect *pb.Rectangle) for { feature, err := stream.Recv() if err == io.EOF { - b, _ := json.Marshal(features) + b := test.MarshalJSON(t)(features) got := string(b) if got != expectedFeatures { t.Error("Failed to get features") diff --git a/gateway/oauth_manager_test.go b/gateway/oauth_manager_test.go index 2d2ec6341b1..5ef91f54014 100644 --- a/gateway/oauth_manager_test.go +++ b/gateway/oauth_manager_test.go @@ -1237,7 +1237,7 @@ func TestJSONToFormValues(t *testing.T) { "client_secret": "test-client-secret", "grant_type": "password", } - b, _ := json.Marshal(o) + b := test.MarshalJSON(t)(o) r, err := http.NewRequest(http.MethodPost, "/token", bytes.NewReader(b)) if err != nil { t.Fatal(err) diff --git a/gateway/testutil.go b/gateway/testutil.go index eb40da0d982..6d930ba4474 100644 --- a/gateway/testutil.go +++ b/gateway/testutil.go @@ -886,10 +886,7 @@ func TestReqBody(t testing.TB, body interface{}) io.Reader { case nil: return nil default: // JSON objects (structs) - bs, err := json.Marshal(x) - if err != nil { - t.Fatal(err) - } + bs := test.MarshalJSON(t)(x) return bytes.NewReader(bs) } } diff --git a/test/json.go b/test/json.go new file mode 100644 index 00000000000..1a6faa56780 --- /dev/null +++ b/test/json.go @@ -0,0 +1,20 @@ +package test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" +) + +// MarshalJSON returns a closure returning the marshalled json +// while asserting no error occurred during marshalling. +func MarshalJSON(tb testing.TB) func(interface{}) []byte { + tb.Helper() + + return func(in interface{}) []byte { + b, err := json.Marshal(in) + require.NoError(tb, err) + return b + } +} diff --git a/test/json_test.go b/test/json_test.go new file mode 100644 index 00000000000..fbb12f2ae9c --- /dev/null +++ b/test/json_test.go @@ -0,0 +1,14 @@ +package test + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMarshalJSON(t *testing.T) { + value := "foo" + marshal := MarshalJSON(t) + out := marshal(value) + assert.Equal(t, []byte(`"foo"`), out) +} From 378a69bb849e40367374093c05b18b2dc9213e68 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 11:16:26 +0300 Subject: [PATCH 28/33] Merging to release-4-lts: [TT-5988] Use defaults APISpec if no API ID found (inactive or deleted) (#5423) (#5749) [TT-5988] Use defaults APISpec if no API ID found (inactive or deleted) (#5423) https://tyktech.atlassian.net/browse/TT-5988 Before: ![image](https://github.com/TykTechnologies/tyk/assets/233360/8e2b6b60-5ef1-49a3-a1b7-6014b3de5218) After: ![image](https://github.com/TykTechnologies/tyk/assets/233360/c42fd8f0-de85-4905-b3c0-fdf3f5685993) Final recorded key data: ``` { "last_check": 0, "allowance": 1000, "rate": 1000, "per": 60, "throttle_interval": -1, "throttle_retry_limit": -1, "max_query_depth": -1, "date_created": "2023-08-16T12:21:53.662653883Z", "expires": 1693398822, "quota_max": -1, "quota_renews": 1692190432, "quota_remaining": 0, "quota_renewal_rate": -1, "access_rights": { "b07c5d3d288f42674a2770aa31981f48": { "api_name": "api 2", "api_id": "b07c5d3d288f42674a2770aa31981f48", "versions": [ "Default" ], "allowed_urls": null, "restricted_types": [], "allowed_types": null, "limit": { "rate": 0, "per": 0, "throttle_interval": 0, "throttle_retry_limit": 0, "max_query_depth": 0, "quota_max": 0, "quota_renews": 0, "quota_remaining": 0, "quota_renewal_rate": 0 }, "field_access_rights": [], "disable_introspection": false, "allowance_scope": "" }, "d77069245b9444766c399015c903c1fb": { "api_name": "api 1", "api_id": "d77069245b9444766c399015c903c1fb", "versions": [ "Default" ], "allowed_urls": null, "restricted_types": [], "allowed_types": null, "limit": { "rate": 0, "per": 0, "throttle_interval": 0, "throttle_retry_limit": 0, "max_query_depth": 0, "quota_max": 0, "quota_renews": 0, "quota_remaining": 0, "quota_renewal_rate": 0 }, "field_access_rights": [], "disable_introspection": false, "allowance_scope": "" } }, "org_id": "64dcbf11a164cd000109d282", "oauth_client_id": "", "oauth_keys": null, "certificate": "", "basic_auth_data": { "password": "", "hash_type": "" }, "jwt_data": { "secret": "" }, "hmac_enabled": false, "enable_http_signature_validation": false, "hmac_string": "", "rsa_certificate_id": "", "is_inactive": false, "apply_policy_id": "", "apply_policies": [], "data_expires": 0, "monitor": { "trigger_limits": null }, "enable_detail_recording": false, "enable_detailed_recording": false, "meta_data": {}, "tags": [], "alias": "", "last_updated": "1692190433", "id_extractor_deadline": 0, "session_lifetime": 0 } ``` API 2 is inactive and honored in access_rights above: ![image](https://github.com/TykTechnologies/tyk/assets/233360/bf75d695-6543-4038-82a9-e80905654df7) PR also addresses some found defects: 1. logging was inconsistent/spaghetti code (now we log with same log fields in function), 2. pre-existing errors - added a `test.JSONMarshal(t)` utility to assert no errors occured (sonarcloud) 3. updated tests to ensure coverage for the change --------- Co-authored-by: Tit Petric [TT-5988]: https://tyktech.atlassian.net/browse/TT-5988?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: Tit Petric --- gateway/api.go | 103 +++++++++++++++++++------------------------- gateway/api_test.go | 7 +++ 2 files changed, 52 insertions(+), 58 deletions(-) diff --git a/gateway/api.go b/gateway/api.go index 42c786511e0..974c265d924 100644 --- a/gateway/api.go +++ b/gateway/api.go @@ -210,11 +210,8 @@ func (gw *Gateway) applyPoliciesAndSave(keyName string, session *user.SessionSta // calculate lifetime considering access rights lifetime := gw.ApplyLifetime(session, spec) - if err := gw.GlobalSessionManager.UpdateSession(keyName, session, lifetime, isHashed); err != nil { - return err - } - return nil + return gw.GlobalSessionManager.UpdateSession(keyName, session, lifetime, isHashed) } // GetApiSpecsFromAccessRights from the session.AccessRights returns the collection of api specs @@ -270,48 +267,54 @@ func (gw *Gateway) doAddOrUpdate(keyName string, newSession *user.SessionState, newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix())) } + logger := log.WithFields(logrus.Fields{ + "prefix": "api", + "key": gw.obfuscateKey(keyName), + "org_id": newSession.OrgID, + "expires": newSession.Expires, + "api_id": "--", + "user_id": "system", + "user_ip": "--", + "path": "--", + "server_name": "system", + }) + if len(newSession.AccessRights) > 0 { // reset API-level limit to empty APILimit if any has a zero-value resetAPILimits(newSession.AccessRights) + // We have a specific list of access rules, only add / update those for apiId := range newSession.AccessRights { apiSpec := gw.getApiSpec(apiId) if apiSpec == nil { - log.WithFields(logrus.Fields{ - "prefix": "api", - "key": keyName, - "org_id": newSession.OrgID, - "api_id": apiId, - "user_id": "system", - "user_ip": "--", - "path": "--", - "server_name": "system", - }).Error("Could not add key for this API ID, API doesn't exist.") - return errors.New("API must be active to add keys") + logger.WithField("api_id", apiId).Warn("Can't find active API, storing anyway") + } + + if apiSpec != nil { + gw.checkAndApplyTrialPeriod(keyName, newSession, isHashed) } - gw.checkAndApplyTrialPeriod(keyName, newSession, isHashed) // Lets reset keys if they are edited by admin - if !apiSpec.DontSetQuotasOnCreate { + if apiSpec == nil || !apiSpec.DontSetQuotasOnCreate { // Reset quote by default if !dontReset { gw.GlobalSessionManager.ResetQuota(keyName, newSession, isHashed) newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate } + } - // apply polices (if any) and save key - if err := gw.applyPoliciesAndSave(keyName, newSession, apiSpec, isHashed); err != nil { - return err - } + // apply polices (if any) and save key + if err := gw.applyPoliciesAndSave(keyName, newSession, apiSpec, isHashed); err != nil { + return err } } } else { // nothing defined, add key to ALL if !gw.GetConfig().AllowMasterKeys { - log.Error("Master keys disallowed in configuration, key not added.") + logger.Error("Master keys disallowed in configuration, key not added.") return errors.New("Master keys not allowed") } - log.Warning("No API Access Rights set, adding key to ALL.") + logger.Warning("No API Access Rights set, adding key to ALL.") gw.apisMu.RLock() defer gw.apisMu.RUnlock() @@ -328,17 +331,7 @@ func (gw *Gateway) doAddOrUpdate(keyName string, newSession *user.SessionState, } } - log.WithFields(logrus.Fields{ - "prefix": "api", - "key": gw.obfuscateKey(keyName), - "expires": newSession.Expires, - "org_id": newSession.OrgID, - "api_id": "--", - "user_id": "system", - "user_ip": "--", - "path": "--", - "server_name": "system", - }).Info("Key added or updated.") + logger.Info("Key added or updated.") return nil } @@ -1375,9 +1368,13 @@ func (gw *Gateway) createKeyHandler(w http.ResponseWriter, r *http.Request) { newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix())) newSession.DateCreated = time.Now() + sessionManager := gw.GlobalSessionManager + mw := BaseMiddleware{Gw: gw} - // TODO: handle apply policies error - mw.ApplyPolicies(newSession) + if err := mw.ApplyPolicies(newSession); err != nil { + doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error())) + return + } if len(newSession.AccessRights) > 0 { // reset API-level limit to nil if any has a zero-value @@ -1386,28 +1383,18 @@ func (gw *Gateway) createKeyHandler(w http.ResponseWriter, r *http.Request) { apiSpec := gw.getApiSpec(apiID) if apiSpec != nil { gw.checkAndApplyTrialPeriod(newKey, newSession, false) - // If we have enabled HMAC checking for keys, we need to generate a secret for the client to use - if !apiSpec.DontSetQuotasOnCreate { - // Reset quota by default - gw.GlobalSessionManager.ResetQuota(newKey, newSession, false) - newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate - } - // apply polices (if any) and save key - if err := gw.applyPoliciesAndSave(newKey, newSession, apiSpec, false); err != nil { - doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error())) - return - } - } else { - // Use fallback - sessionManager := gw.GlobalSessionManager + } + + if apiSpec == nil || !apiSpec.DontSetQuotasOnCreate { + // Reset quota by default newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate sessionManager.ResetQuota(newKey, newSession, false) - // apply polices (if any) and save key - err := sessionManager.UpdateSession(newKey, newSession, -1, false) - if err != nil { - doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error())) - return - } + } + + // apply polices (if any) and save key + if err := gw.applyPoliciesAndSave(newKey, newSession, apiSpec, false); err != nil { + doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error())) + return } } } else { @@ -1429,8 +1416,8 @@ func (gw *Gateway) createKeyHandler(w http.ResponseWriter, r *http.Request) { for _, spec := range gw.apisByID { gw.checkAndApplyTrialPeriod(newKey, newSession, false) if !spec.DontSetQuotasOnCreate { - // Reset quote by default - gw.GlobalSessionManager.ResetQuota(newKey, newSession, false) + // Reset quota by default + sessionManager.ResetQuota(newKey, newSession, false) newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate } if err := gw.applyPoliciesAndSave(newKey, newSession, spec, false); err != nil { diff --git a/gateway/api_test.go b/gateway/api_test.go index a75fcaaf64b..fc508086d13 100644 --- a/gateway/api_test.go +++ b/gateway/api_test.go @@ -187,6 +187,12 @@ func TestKeyHandler(t *testing.T) { } withBadPolicyJSON := test.MarshalJSON(t)(withBadPolicy) + withUnknownAPI := CreateStandardSession() + withUnknownAPI.AccessRights = map[string]user.AccessDefinition{"unknown": { + APIID: "unknown", Versions: []string{"v1"}, + }} + withUnknownAPIJSON := test.MarshalJSON(t)(withUnknownAPI) + t.Run("Create key", func(t *testing.T) { ts.Run(t, []test.TestCase{ // Master keys should be disabled by default @@ -323,6 +329,7 @@ func TestKeyHandler(t *testing.T) { // Without data {Method: "PUT", Path: "/tyk/keys/" + knownKey, AdminAuth: true, Code: 400}, {Method: "PUT", Path: "/tyk/keys/" + knownKey, Data: string(withAccessJSON), AdminAuth: true, Code: 200}, + {Method: "PUT", Path: "/tyk/keys/" + knownKey, Data: string(withUnknownAPIJSON), AdminAuth: true, Code: 200}, {Method: "PUT", Path: "/tyk/keys/" + knownKey + "?api_id=test", Data: string(withAccessJSON), AdminAuth: true, Code: 200}, {Method: "PUT", Path: "/tyk/keys/" + knownKey + "?api_id=none", Data: string(withAccessJSON), AdminAuth: true, Code: 200}, }...) From f4e5cab5c847d8d082d36c7b30a748e4e763c39a Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Tue, 7 Nov 2023 11:18:31 +0300 Subject: [PATCH 29/33] Merging to release-4-lts: [TT-6446] Minimal approach to setting a context-enforced timeout (#5541) (#5748) [TT-6446] Minimal approach to setting a context-enforced timeout (#5541) This changes the default proxy timeout to not be based on HardTimeout configured from an APISpec. - If a hard timeout is configured, a context with timeout is created for the outgoing request, - The transport timeout is configured to [proxy_default_timeout](https://tyk.io/docs/tyk-oss-gateway/configuration/#proxy_default_timeout) or 30 secs by default. https://tyktech.atlassian.net/browse/TT-6446 --------- Co-authored-by: Tit Petric Co-authored-by: Furkan Senharputlu [TT-6446]: https://tyktech.atlassian.net/browse/TT-6446?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Tit Petric Co-authored-by: Tit Petric --- gateway/reverse_proxy.go | 45 +++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/gateway/reverse_proxy.go b/gateway/reverse_proxy.go index 7eccdb4c372..b795af0d07d 100644 --- a/gateway/reverse_proxy.go +++ b/gateway/reverse_proxy.go @@ -528,20 +528,34 @@ func (p *ReverseProxy) ServeHTTPForCache(rw http.ResponseWriter, req *http.Reque return resp } +const defaultProxyTimeout float64 = 30 + +func proxyTimeout(spec *APISpec) float64 { + if spec.GlobalConfig.ProxyDefaultTimeout > 0 { + return spec.GlobalConfig.ProxyDefaultTimeout + } + return defaultProxyTimeout +} + +// CheckHardTimeoutEnforced checks APISpec versions for a fine grained timeout +// value. The value is defined in seconds, but we're using float64 to enable +// sub-second durations for tests. Changing to int would break that behaviour. func (p *ReverseProxy) CheckHardTimeoutEnforced(spec *APISpec, req *http.Request) (bool, float64) { if !spec.EnforcedTimeoutEnabled { - return false, spec.GlobalConfig.ProxyDefaultTimeout + return false, 0 } _, versionPaths, _, _ := spec.Version(req) found, meta := spec.CheckSpecMatchesStatus(req, versionPaths, HardTimeout) if found { - intMeta := meta.(*int) - p.logger.Debug("HARD TIMEOUT ENFORCED: ", *intMeta) - return true, float64(*intMeta) + intMeta, ok := meta.(*int) + if ok && *intMeta > 0 { + p.logger.Debug("HARD TIMEOUT ENFORCED: ", *intMeta) + return true, float64(*intMeta) + } } - return false, spec.GlobalConfig.ProxyDefaultTimeout + return false, 0 } func (p *ReverseProxy) CheckHeaderInRemoveList(hdr string, spec *APISpec, req *http.Request) bool { @@ -1268,6 +1282,16 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques p.TykAPISpec.Lock() + isTimeoutEnforced, enforcedTimeout := p.CheckHardTimeoutEnforced(p.TykAPISpec, outreq) + + // limit request time with context timeout + if isTimeoutEnforced { + timeoutContext, cancel := context.WithTimeout(outreq.Context(), time.Duration(enforcedTimeout)*time.Second) + defer cancel() + + outreq = outreq.WithContext(timeoutContext) + } + // create HTTP transport createTransport := p.TykAPISpec.HTTPTransport == nil @@ -1285,7 +1309,8 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques oldTransport.DisableKeepAlives = true } - _, timeout := p.CheckHardTimeoutEnforced(p.TykAPISpec, req) + timeout := proxyTimeout(p.TykAPISpec) + p.TykAPISpec.HTTPTransport = p.httpTransport(timeout, rw, req, outreq) p.TykAPISpec.HTTPTransportCreated = time.Now() @@ -1364,7 +1389,13 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques "org_id": p.TykAPISpec.OrgID, "api_id": p.TykAPISpec.APIID, }).Error("http: proxy error: ", err) - if strings.Contains(err.Error(), "timeout awaiting response headers") { + + if strings.HasPrefix(err.Error(), "mock:") { + p.ErrorHandler.HandleError(rw, logreq, err.Error(), res.StatusCode, true) + return ProxyResponse{UpstreamLatency: upstreamLatency} + } + + if strings.Contains(err.Error(), "timeout awaiting response headers") || strings.Contains(err.Error(), "context deadline exceeded") { p.ErrorHandler.HandleError(rw, logreq, "Upstream service reached hard timeout.", http.StatusGatewayTimeout, true) if p.TykAPISpec.Proxy.ServiceDiscovery.UseDiscoveryService { From c7375e80177dbb843283d09caa07ff190bd1c1d1 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 7 Dec 2023 17:39:09 +0300 Subject: [PATCH 30/33] Merging to release-4-lts: TT-10701, fix for urlRewrite encoding issue (#5835) TT-10701, fix for urlRewrite encoding issue (#5835) ## Description Adapted logic such that the middleware is run only once but with the caveat that if no matches are found using the urlEncoded path, another regex match check is done but this time with the path decoded. This should allow for backwards compatibility and even improve performance. ## Related Issue ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --- gateway/mw_url_rewrite.go | 24 ++++++++++-------------- gateway/mw_url_rewrite_test.go | 24 ++++++++++++++++++++---- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/gateway/mw_url_rewrite.go b/gateway/mw_url_rewrite.go index a4fae14302a..8fc735b5543 100644 --- a/gateway/mw_url_rewrite.go +++ b/gateway/mw_url_rewrite.go @@ -38,18 +38,10 @@ var envValueMatch = regexp.MustCompile(`\$secret_env.([A-Za-z0-9_\-\.]+)`) var metaMatch = regexp.MustCompile(`\$tyk_meta.([A-Za-z0-9_\-\.]+)`) var secretsConfMatch = regexp.MustCompile(`\$secret_conf.([A-Za-z0-9[.\-\_]+)`) -func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request, decodeURL bool) (string, error) { +func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request) (string, error) { rawPath := r.URL.String() path := rawPath - if decodeURL { - var err error - path, err = url.PathUnescape(rawPath) - if err != nil { - return rawPath, fmt.Errorf("failed to decode URL path: %s", rawPath) - } - } - log.Debug("Inbound path: ", path) newpath := path @@ -176,6 +168,14 @@ func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request, deco } matchGroups := meta.MatchRegexp.FindAllStringSubmatch(path, -1) + if len(matchGroups) == 0 && containsEscapedChars(rawPath) { + unescapedPath, err := url.PathUnescape(rawPath) + if err != nil { + return unescapedPath, fmt.Errorf("failed to decode URL path: %s", rawPath) + } + + matchGroups = meta.MatchRegexp.FindAllStringSubmatch(unescapedPath, -1) + } // Make sure it matches the string log.Debug("Rewriter checking matches, len is: ", len(matchGroups)) @@ -206,10 +206,6 @@ func (gw *Gateway) urlRewrite(meta *apidef.URLRewriteMeta, r *http.Request, deco newpath = gw.replaceTykVariables(r, newpath, true) - if rawPath == newpath && containsEscapedChars(rawPath) { - newpath, _ = gw.urlRewrite(meta, r, true) - } - return newpath, nil } @@ -493,7 +489,7 @@ func (m *URLRewriteMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Req log.Debug(r.URL) oldPath := r.URL.String() - p, err := m.Gw.urlRewrite(umeta, r, false) + p, err := m.Gw.urlRewrite(umeta, r) if err != nil { log.Error(err) return err, http.StatusInternalServerError diff --git a/gateway/mw_url_rewrite_test.go b/gateway/mw_url_rewrite_test.go index 7b7bc45afc2..7ffd51d415a 100644 --- a/gateway/mw_url_rewrite_test.go +++ b/gateway/mw_url_rewrite_test.go @@ -39,6 +39,16 @@ var testRewriterData = []struct { "test/val/(.*)", "change/to/$1", "/test/val/VALUE", "change/to/VALUE", }, + { + "OneVal Special Case", + "test/val/(.*)", "/test/val/$1", + "/test/val/VALUE%2C", "/test/val/VALUE%2C", + }, + { + "OneVal Special Case With Query Param Encoded", + "test/val/(.*)", "/test/val/$1", + "/test/val/VALUE%2C?a=te%2Cst", "/test/val/VALUE%2C?a=te%2Cst", + }, { "ThreeVals", "/test/val/(.*)/space/(.*)/and/then/(.*)", "/change/to/$1/$2/$3", @@ -105,7 +115,7 @@ func TestRewriter(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { r := tc.reqMaker() - got, err := ts.Gw.urlRewrite(tc.meta, r, false) + got, err := ts.Gw.urlRewrite(tc.meta, r) if err != nil { t.Error("compile failed:", err) } @@ -123,7 +133,10 @@ func BenchmarkRewriter(b *testing.B) { //warm-up regexp caches for _, tc := range cases { r := tc.reqMaker() - ts.Gw.urlRewrite(tc.meta, r, false) + _, err := ts.Gw.urlRewrite(tc.meta, r) + if err != nil { + b.Errorf("benchmark failed %s", err.Error()) + } } b.ReportAllocs() @@ -133,7 +146,10 @@ func BenchmarkRewriter(b *testing.B) { b.StopTimer() r := tc.reqMaker() b.StartTimer() - ts.Gw.urlRewrite(tc.meta, r, false) + _, err := ts.Gw.urlRewrite(tc.meta, r) + if err != nil { + b.Errorf("benchmark failed %s", err.Error()) + } } } } @@ -1091,7 +1107,7 @@ func TestRewriterTriggers(t *testing.T) { Triggers: tc.triggerConf, } - got, err := ts.Gw.urlRewrite(&testConf, tc.req, false) + got, err := ts.Gw.urlRewrite(&testConf, tc.req) if err != nil { t.Error("compile failed:", err) } From 43645f72cefa95ca0a43ee52af1aebd3485ff7f4 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Thu, 21 Dec 2023 13:01:01 +0300 Subject: [PATCH 31/33] Merging to release-4-lts: [TT-10189/TT-10467] Add OAuthPurgeLapsedTokens (#5766) (#5901) [TT-10189/TT-10467] Add OAuthPurgeLapsedTokens (#5766) ## Description This PR adds an event `OAuthPurgeLapsedTokens`, which upon receiving would delete all lapsed OAuth tokens. It also adds endpoint `DELETE /tyk/oauth/tokens?scope=lapsed` to purge lapsed OAuth tokens synchronously. What are lapsed OAuth tokens? Lapsed OAuth tokens that are expired and past `oauth_token_expired_retain_period` configured in gateway config. ## Related Issue Sub Task: https://tyktech.atlassian.net/browse/TT-10467 Parent Ticket: https://tyktech.atlassian.net/browse/TT-10189 ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --------- Co-authored-by: dcs3spp --------- Co-authored-by: Jeffy Mathew --- gateway/api.go | 60 ++++++++++++----- gateway/api_test.go | 68 +++++++++++++++++++ gateway/oauth_manager.go | 55 +++++++++++++-- gateway/oauth_manager_test.go | 86 ++++++++++++++++++++++++ gateway/redis_signals.go | 5 ++ gateway/server.go | 1 + go.mod | 5 ++ go.sum | 3 + internal/errors/errors.go | 15 +++++ internal/errors/errors_test.go | 39 +++++++++++ internal/url/url.go | 11 +++ internal/url/url_test.go | 55 +++++++++++++++ storage/redis_cluster.go | 119 +++++++++++++++++++-------------- 13 files changed, 449 insertions(+), 73 deletions(-) create mode 100644 internal/errors/errors.go create mode 100644 internal/errors/errors_test.go create mode 100644 internal/url/url.go create mode 100644 internal/url/url_test.go diff --git a/gateway/api.go b/gateway/api.go index 974c265d924..422ff8d4a60 100644 --- a/gateway/api.go +++ b/gateway/api.go @@ -3,24 +3,24 @@ // The code below describes the Tyk Gateway API // Version: 2.8.0 // -// Schemes: https, http -// Host: localhost -// BasePath: /tyk/ +// Schemes: https, http +// Host: localhost +// BasePath: /tyk/ // -// Consumes: -// - application/json +// Consumes: +// - application/json // -// Produces: -// - application/json +// Produces: +// - application/json // -// Security: -// - api_key: +// Security: +// - api_key: // -// SecurityDefinitions: -// api_key: -// type: apiKey -// name: X-Tyk-Authorization -// in: header +// SecurityDefinitions: +// api_key: +// type: apiKey +// name: X-Tyk-Authorization +// in: header // // swagger:meta package gateway @@ -34,7 +34,6 @@ import ( "fmt" "io/ioutil" "net/http" - "net/url" "os" "path/filepath" "strconv" @@ -51,6 +50,7 @@ import ( "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/ctx" "github.com/TykTechnologies/tyk/headers" + "github.com/TykTechnologies/tyk/internal/url" "github.com/TykTechnologies/tyk/storage" "github.com/TykTechnologies/tyk/user" @@ -59,6 +59,14 @@ import ( "github.com/TykTechnologies/tyk/internal/uuid" ) +const ( + oAuthClientTokensKeyPattern = "oauth-data.*oauth-client-tokens.*" +) + +var ( + ErrRequestMalformed = errors.New("request malformed") +) + // apiModifyKeySuccess represents when a Key modification was successful // // swagger:model apiModifyKeySuccess @@ -340,7 +348,6 @@ func (gw *Gateway) doAddOrUpdate(keyName string, newSession *user.SessionState, // remove from all stores, update to all stores, stores handle quotas separately though because they are localised! Keys will // need to be managed by API, but only for GetDetail, GetList, UpdateKey and DeleteKey -// func (gw *Gateway) setBasicAuthSessionPassword(session *user.SessionState) { basicAuthHashAlgo := gw.basicAuthHashAlgo() @@ -1319,7 +1326,6 @@ func (gw *Gateway) groupResetHandler(w http.ResponseWriter, r *http.Request) { // was in the URL parameters, it will block until the reload is done. // Otherwise, it won't block and fn will be called once the reload is // finished. -// func (gw *Gateway) resetHandler(fn func()) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var wg sync.WaitGroup @@ -2046,6 +2052,26 @@ func (gw *Gateway) getOauthClientDetails(keyName, apiID string) (interface{}, in return reportableClientData, http.StatusOK } +func (gw *Gateway) oAuthTokensHandler(w http.ResponseWriter, r *http.Request) { + if !url.QueryHas(r.URL.Query(), "scope") { + doJSONWrite(w, http.StatusUnprocessableEntity, apiError("scope parameter is required")) + return + } + + if r.URL.Query().Get("scope") != "lapsed" { + doJSONWrite(w, http.StatusBadRequest, apiError("unknown scope")) + return + } + + err := gw.purgeLapsedOAuthTokens() + if err != nil { + doJSONWrite(w, http.StatusInternalServerError, apiError("error purging lapsed tokens")) + return + } + + doJSONWrite(w, http.StatusOK, apiOk("lapsed tokens purged")) +} + // Delete Client func (gw *Gateway) handleDeleteOAuthClient(keyName, apiID string) (interface{}, int) { storageID := oauthClientStorageID(keyName) diff --git a/gateway/api_test.go b/gateway/api_test.go index fc508086d13..a6a52bd616d 100644 --- a/gateway/api_test.go +++ b/gateway/api_test.go @@ -2042,3 +2042,71 @@ func TestOrgKeyHandler_LastUpdated(t *testing.T) { }}, }...) } + +func TestPurgeOAuthClientTokens(t *testing.T) { + conf := func(globalConf *config.Config) { + // set tokens to be expired after 1 second + globalConf.OauthTokenExpire = 1 + // cleanup tokens older than 2 seconds + globalConf.OauthTokenExpiredRetainPeriod = 2 + } + + ts := StartTest(conf) + defer ts.Close() + + t.Run("scope validation", func(t *testing.T) { + ts.Run(t, []test.TestCase{ + { + AdminAuth: true, + Path: "/tyk/oauth/tokens/", + Method: http.MethodDelete, + Code: http.StatusUnprocessableEntity, + }, + { + AdminAuth: true, + Path: "/tyk/oauth/tokens/", + QueryParams: map[string]string{"scope": "expired"}, + Method: http.MethodDelete, + Code: http.StatusBadRequest, + }, + }...) + }) + + assertTokensLen := func(t *testing.T, storageManager storage.Handler, storageKey string, expectedTokensLen int) { + nowTs := time.Now().Unix() + startScore := strconv.FormatInt(nowTs, 10) + tokens, _, err := storageManager.GetSortedSetRange(storageKey, startScore, "+inf") + assert.NoError(t, err) + assert.Equal(t, expectedTokensLen, len(tokens)) + } + + t.Run("scope=lapsed", func(t *testing.T) { + spec := ts.LoadTestOAuthSpec() + + clientID1, clientID2 := uuid.New(), uuid.New() + + ts.createOAuthClientIDAndTokens(t, spec, clientID1) + ts.createOAuthClientIDAndTokens(t, spec, clientID2) + storageKey1, storageKey2 := fmt.Sprintf("%s%s", prefixClientTokens, clientID1), + fmt.Sprintf("%s%s", prefixClientTokens, clientID2) + + storageManager := ts.Gw.getGlobalStorageHandler(generateOAuthPrefix(spec.APIID), false) + storageManager.Connect() + + assertTokensLen(t, storageManager, storageKey1, 3) + assertTokensLen(t, storageManager, storageKey2, 3) + + time.Sleep(time.Second * 3) + ts.Run(t, test.TestCase{ + ControlRequest: true, + AdminAuth: true, + Path: "/tyk/oauth/tokens", + QueryParams: map[string]string{"scope": "lapsed"}, + Method: http.MethodDelete, + Code: http.StatusOK, + }) + + assertTokensLen(t, storageManager, storageKey1, 0) + assertTokensLen(t, storageManager, storageKey2, 0) + }) +} diff --git a/gateway/oauth_manager.go b/gateway/oauth_manager.go index 84e66e94c9c..90a870c3246 100644 --- a/gateway/oauth_manager.go +++ b/gateway/oauth_manager.go @@ -10,19 +10,21 @@ import ( "net/http" "net/url" "strings" + "sync" "time" "github.com/TykTechnologies/tyk/request" - "github.com/sirupsen/logrus" - + "github.com/hashicorp/go-multierror" "github.com/lonelycode/osin" + "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" - "github.com/TykTechnologies/tyk/internal/uuid" - "strconv" + "github.com/TykTechnologies/tyk/internal/uuid" + "github.com/TykTechnologies/tyk/headers" + tykerrors "github.com/TykTechnologies/tyk/internal/errors" "github.com/TykTechnologies/tyk/storage" "github.com/TykTechnologies/tyk/user" ) @@ -1186,3 +1188,48 @@ func (r *RedisOsinStorageInterface) SetUser(username string, session *user.Sessi return nil } + +func (gw *Gateway) purgeLapsedOAuthTokens() error { + if gw.GetConfig().OauthTokenExpiredRetainPeriod <= 0 { + return nil + } + + redisCluster := &storage.RedisCluster{KeyPrefix: "", HashKeys: false, RedisController: gw.RedisController} + keys, err := redisCluster.ScanKeys(oAuthClientTokensKeyPattern) + + if err != nil { + log.WithError(err).Debug("error while scanning for tokens") + return err + } + + nowTs := time.Now().Unix() + // clean up expired tokens in sorted set (remove all tokens with score up to current timestamp minus retention) + cleanupStartScore := strconv.FormatInt(nowTs-int64(gw.GetConfig().OauthTokenExpiredRetainPeriod), 10) + + var wg sync.WaitGroup + + errs := make(chan error, len(keys)) + for _, key := range keys { + wg.Add(1) + go func(k string) { + defer wg.Done() + if err := redisCluster.RemoveSortedSetRange(k, "-inf", cleanupStartScore); err != nil { + errs <- err + } + }(key) + } + + // Wait for all goroutines to finish + wg.Wait() + close(errs) + + combinedErr := &multierror.Error{ + ErrorFormat: tykerrors.Formatter, + } + + for err := range errs { + combinedErr = multierror.Append(combinedErr, err) + } + + return combinedErr.ErrorOrNil() +} diff --git a/gateway/oauth_manager_test.go b/gateway/oauth_manager_test.go index 5ef91f54014..69fee07a1a6 100644 --- a/gateway/oauth_manager_test.go +++ b/gateway/oauth_manager_test.go @@ -8,7 +8,9 @@ import ( "bytes" "encoding/json" "net/url" + "path" "reflect" + "strconv" "strings" "testing" @@ -150,6 +152,41 @@ func (ts *Test) createTestOAuthClient(spec *APISpec, clientID string) OAuthClien return testClient } +func (ts *Test) createOAuthClientIDAndTokens(t *testing.T, spec *APISpec, clientID string) { + t.Helper() + ts.createTestOAuthClient(spec, clientID) + + param := make(url.Values) + param.Set("response_type", "token") + param.Set("redirect_uri", authRedirectUri) + param.Set("client_id", clientID) + param.Set("client_secret", authClientSecret) + param.Set("key_rules", keyRules) + + headers := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + for i := 0; i < 3; i++ { + resp, err := ts.Run(t, test.TestCase{ + Path: path.Join(spec.Proxy.ListenPath, "/tyk/oauth/authorize-client/"), + Data: param.Encode(), + AdminAuth: true, + Headers: headers, + Method: http.MethodPost, + Code: http.StatusOK, + }) + if err != nil { + t.Error(err) + } + + response := map[string]interface{}{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + t.Fatal(err) + } + } +} + func TestOauthMultipleAPIs(t *testing.T) { ts := StartTest(nil) defer ts.Close() @@ -1269,3 +1306,52 @@ func TestJSONToFormValues(t *testing.T) { } }) } + +func TestPurgeOAuthClientTokensEvent(t *testing.T) { + conf := func(globalConf *config.Config) { + // set tokens to be expired after 1 second + globalConf.OauthTokenExpire = 1 + // cleanup tokens older than 2 seconds + globalConf.OauthTokenExpiredRetainPeriod = 2 + } + + ts := StartTest(conf) + defer ts.Close() + + assertTokensLen := func(t *testing.T, storageManager storage.Handler, storageKey string, expectedTokensLen int) { + nowTs := time.Now().Unix() + startScore := strconv.FormatInt(nowTs, 10) + tokens, _, err := storageManager.GetSortedSetRange(storageKey, startScore, "+inf") + assert.NoError(t, err) + assert.Equal(t, expectedTokensLen, len(tokens)) + } + + spec := ts.LoadTestOAuthSpec() + + clientID1, clientID2 := uuid.New(), uuid.New() + + ts.createOAuthClientIDAndTokens(t, spec, clientID1) + ts.createOAuthClientIDAndTokens(t, spec, clientID2) + storageKey1, storageKey2 := fmt.Sprintf("%s%s", prefixClientTokens, clientID1), + fmt.Sprintf("%s%s", prefixClientTokens, clientID2) + + storageManager := ts.Gw.getGlobalStorageHandler(generateOAuthPrefix(spec.APIID), false) + storageManager.Connect() + + assertTokensLen(t, storageManager, storageKey1, 3) + assertTokensLen(t, storageManager, storageKey2, 3) + + time.Sleep(time.Second * 3) + + // emit event + + n := Notification{ + Command: OAuthPurgeLapsedTokens, + Gw: ts.Gw, + } + ts.Gw.MainNotifier.Notify(n) + + assertTokensLen(t, storageManager, storageKey1, 0) + assertTokensLen(t, storageManager, storageKey2, 0) + +} diff --git a/gateway/redis_signals.go b/gateway/redis_signals.go index e790d9b5244..e14d569e622 100644 --- a/gateway/redis_signals.go +++ b/gateway/redis_signals.go @@ -34,6 +34,7 @@ const ( NoticeGatewayDRLNotification NotificationCommand = "NoticeGatewayDRLNotification" NoticeGatewayLENotification NotificationCommand = "NoticeGatewayLENotification" KeySpaceUpdateNotification NotificationCommand = "KeySpaceUpdateNotification" + OAuthPurgeLapsedTokens NotificationCommand = "OAuthPurgeLapsedTokens" ) // Notification is a type that encodes a message published to a pub sub channel (shared between implementations) @@ -119,6 +120,10 @@ func (gw *Gateway) handleRedisEvent(v interface{}, handled func(NotificationComm gw.reloadURLStructure(reloaded) case KeySpaceUpdateNotification: gw.handleKeySpaceEventCacheFlush(notif.Payload) + case OAuthPurgeLapsedTokens: + if err := gw.purgeLapsedOAuthTokens(); err != nil { + log.WithError(err).Errorf("error while purging tokens for event %s", OAuthPurgeLapsedTokens) + } default: pubSubLog.Warnf("Unknown notification command: %q", notif.Command) return diff --git a/gateway/server.go b/gateway/server.go index 6a70607623f..72510cd04ba 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -625,6 +625,7 @@ func (gw *Gateway) loadControlAPIEndpoints(muxer *mux.Router) { r.HandleFunc("/oauth/clients/{apiID}", gw.oAuthClientHandler).Methods("GET", "DELETE") r.HandleFunc("/oauth/clients/{apiID}/{keyName:[^/]*}", gw.oAuthClientHandler).Methods("GET", "DELETE") r.HandleFunc("/oauth/clients/{apiID}/{keyName}/tokens", gw.oAuthClientTokensHandler).Methods("GET") + r.HandleFunc("/oauth/tokens", gw.oAuthTokensHandler).Methods(http.MethodDelete) mainLog.Debug("Loaded API Endpoints") } diff --git a/go.mod b/go.mod index 260ad920821..c57865f6b7c 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,9 @@ require ( github.com/hashicorp/go-hclog v0.14.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-retryablehttp v0.6.7 // indirect + github.com/hashicorp/go-version v1.1.0 github.com/hashicorp/memberlist v0.1.6 // indirect github.com/hashicorp/serf v0.8.6 // indirect github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086 @@ -108,3 +110,6 @@ require ( ) //replace github.com/jensneuse/graphql-go-tools => ../graphql-go-tools +replace sourcegraph.com/sourcegraph/appdash => github.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600 + +replace sourcegraph.com/sourcegraph/appdash-data => github.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 diff --git a/go.sum b/go.sum index 0a5099f2c13..0630727129d 100644 --- a/go.sum +++ b/go.sum @@ -271,6 +271,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -519,6 +520,8 @@ github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600/go.mod h1:V952P4GGl1v/MMynLwxVdWEbSZJx+n0oOO3ljnez+WU= +github.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:tNZjgbYncKL5HxvDULAr/mWDmFz4B7H8yrXEDlnoIiw= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= diff --git a/internal/errors/errors.go b/internal/errors/errors.go new file mode 100644 index 00000000000..4faa273d4ae --- /dev/null +++ b/internal/errors/errors.go @@ -0,0 +1,15 @@ +package errors + +import "strings" + +func Formatter(errs []error) string { + var result strings.Builder + for i, err := range errs { + result.WriteString(err.Error()) + if i < len(errs)-1 { + result.WriteString("\n") + } + } + + return result.String() +} diff --git a/internal/errors/errors_test.go b/internal/errors/errors_test.go new file mode 100644 index 00000000000..e4d8f9ff56d --- /dev/null +++ b/internal/errors/errors_test.go @@ -0,0 +1,39 @@ +package errors + +import ( + "errors" + "testing" +) + +func TestErrorFormatter(t *testing.T) { + tests := []struct { + name string + errs []error + expected string + }{ + { + name: "No errors", + errs: []error{}, + expected: "", + }, + { + name: "Single error", + errs: []error{errors.New("error 1")}, + expected: "error 1", + }, + { + name: "Multiple errors", + errs: []error{errors.New("error 1"), errors.New("error 2")}, + expected: "error 1\nerror 2", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := Formatter(tc.errs) + if result != tc.expected { + t.Errorf("Formatter() = %v, want %v", result, tc.expected) + } + }) + } +} diff --git a/internal/url/url.go b/internal/url/url.go new file mode 100644 index 00000000000..8eaa6d050e1 --- /dev/null +++ b/internal/url/url.go @@ -0,0 +1,11 @@ +package url + +import "net/url" + +type URL = url.URL + +// QueryHas checks whether a given key is set. +func QueryHas(v url.Values, key string) bool { + _, ok := v[key] + return ok +} diff --git a/internal/url/url_test.go b/internal/url/url_test.go new file mode 100644 index 00000000000..69490e5f062 --- /dev/null +++ b/internal/url/url_test.go @@ -0,0 +1,55 @@ +package url + +import ( + "net/url" + "testing" +) + +func TestQueryHas(t *testing.T) { + tests := []struct { + name string + values url.Values + key string + expected bool + }{ + { + name: "Key present", + values: url.Values{"test": []string{"value"}}, + key: "test", + expected: true, + }, + { + name: "Key absent", + values: url.Values{"test": []string{"value"}}, + key: "missing", + expected: false, + }, + { + name: "Empty values", + values: url.Values{}, + key: "any", + expected: false, + }, + { + name: "Multiple keys, target present", + values: url.Values{"test": []string{"value"}, "another": []string{"value2"}}, + key: "another", + expected: true, + }, + { + name: "Multiple keys, target absent", + values: url.Values{"test": []string{"value"}, "another": []string{"value2"}}, + key: "missing", + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := QueryHas(tt.values, tt.key) + if result != tt.expected { + t.Errorf("QueryHas(%v, %q) = %v; want %v", tt.values, tt.key, result, tt.expected) + } + }) + } +} diff --git a/storage/redis_cluster.go b/storage/redis_cluster.go index 26f8791a42c..e37c70599fa 100644 --- a/storage/redis_cluster.go +++ b/storage/redis_cluster.go @@ -430,64 +430,15 @@ func (r *RedisCluster) IncrememntWithExpire(keyName string, expire int64) int64 // GetKeys will return all keys according to the filter (filter is a prefix - e.g. tyk.keys.*) func (r *RedisCluster) GetKeys(filter string) []string { - if err := r.up(); err != nil { - log.Debug(err) - return nil - } - - singleton, err := r.singleton() - if err != nil { - log.Error(err) - return nil - } - filterHash := "" if filter != "" { filterHash = r.hashKey(filter) } + searchStr := r.KeyPrefix + filterHash + "*" log.Debug("[STORE] Getting list by: ", searchStr) - fnFetchKeys := func(client *redis.Client) ([]string, error) { - values := make([]string, 0) - - iter := client.Scan(r.RedisController.ctx, 0, searchStr, 0).Iterator() - for iter.Next(r.RedisController.ctx) { - values = append(values, iter.Val()) - } - - if err := iter.Err(); err != nil { - return nil, err - } - - return values, nil - } - - sessions := make([]string, 0) - - switch v := singleton.(type) { - case *redis.ClusterClient: - ch := make(chan []string) - - go func() { - err = v.ForEachMaster(r.RedisController.ctx, func(ctx context.Context, client *redis.Client) error { - values, err := fnFetchKeys(client) - if err != nil { - return err - } - - ch <- values - return nil - }) - close(ch) - }() - - for res := range ch { - sessions = append(sessions, res...) - } - case *redis.Client: - sessions, err = fnFetchKeys(v) - } + sessions, err := r.ScanKeys(searchStr) if err != nil { log.Error("Error while fetching keys:", err) @@ -1148,7 +1099,7 @@ func (r *RedisCluster) SetRollingWindow(keyName string, per int64, value_overrid return intVal, result } -func (r RedisCluster) GetRollingWindow(keyName string, per int64, pipeline bool) (int, []interface{}) { +func (r *RedisCluster) GetRollingWindow(keyName string, per int64, pipeline bool) (int, []interface{}) { if err := r.up(); err != nil { log.Debug(err) return 0, nil @@ -1298,3 +1249,67 @@ func (r *RedisCluster) RemoveSortedSetRange(keyName, scoreFrom, scoreTo string) func (r *RedisCluster) ControllerInitiated() bool { return r.RedisController != nil } + +// ScanKeys will return all keys according to the pattern. +func (r *RedisCluster) ScanKeys(pattern string) ([]string, error) { + if err := r.up(); err != nil { + log.Debug(err) + return nil, err + } + + singleton, err := r.singleton() + if err != nil { + log.Error(err) + return nil, err + } + + log.Debug("[STORE] scanning keys by: ", pattern) + + fnFetchKeys := func(client *redis.Client) ([]string, error) { + values := make([]string, 0) + + iter := client.Scan(r.RedisController.ctx, 0, pattern, 0).Iterator() + for iter.Next(r.RedisController.ctx) { + values = append(values, iter.Val()) + } + + if err := iter.Err(); err != nil { + return nil, err + } + + return values, nil + } + + keys := make([]string, 0) + + switch v := singleton.(type) { + case *redis.ClusterClient: + ch := make(chan []string) + + go func() { + err = v.ForEachMaster(r.RedisController.ctx, func(ctx context.Context, client *redis.Client) error { + values, err := fnFetchKeys(client) + if err != nil { + return err + } + + ch <- values + return nil + }) + close(ch) + }() + + for res := range ch { + keys = append(keys, res...) + } + case *redis.Client: + keys, err = fnFetchKeys(v) + } + + if err != nil { + log.Error("Error while scanning for keys:", err) + return nil, err + } + + return keys, nil +} From 29dee3388a99237125f60fdf7d7bca0fd5f05b90 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 29 Dec 2023 15:03:51 +0300 Subject: [PATCH 32/33] Merging to release-4-lts: [TT-10826] self trim oAuth sorted set (#5907) (#5916) [TT-10826] self trim oAuth sorted set (#5907) ## Description Add a background job to self trim oAuth sorted set ## Related Issue https://tyktech.atlassian.net/browse/TT-10826 ## Motivation and Context ## How This Has Been Tested ## Screenshots (if appropriate) ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why --------- Co-authored-by: Tit Petric Co-authored-by: Tit Petric [TT-10826]: https://tyktech.atlassian.net/browse/TT-10826?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Jeffy Mathew --- bin/run-benchmarks.sh | 7 + cli/linter/linter.go | 6 +- config/config.go | 13 +- config/config_test.go | 6 +- config/private.go | 22 +++ config/private_test.go | 20 +++ config/util.go | 24 +++ config/util_test.go | 63 +++++++ gateway/api_test.go | 2 +- gateway/oauth_manager.go | 27 ++- gateway/oauth_manager_test.go | 241 +++++++++++++++++++++++--- gateway/redis_signal_handle_config.go | 2 +- gateway/server.go | 16 +- go.mod | 7 +- go.sum | 50 ++++-- internal/errors/errors.go | 11 +- internal/scheduler/scheduler.go | 105 +++++++++++ internal/scheduler/scheduler_test.go | 76 ++++++++ storage/redis_cluster.go | 36 ++-- storage/redis_cluster_test.go | 87 +++++++++- storage/redis_controller.go | 8 + 21 files changed, 737 insertions(+), 92 deletions(-) create mode 100755 bin/run-benchmarks.sh create mode 100644 config/private.go create mode 100644 config/private_test.go create mode 100644 config/util.go create mode 100644 config/util_test.go create mode 100644 internal/scheduler/scheduler.go create mode 100644 internal/scheduler/scheduler_test.go diff --git a/bin/run-benchmarks.sh b/bin/run-benchmarks.sh new file mode 100755 index 00000000000..f2d0b0c73fe --- /dev/null +++ b/bin/run-benchmarks.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Running benchmarks" + + +go test -json -benchtime 30s -run='^$' -bench BenchmarkPurgeLapsedOAuthTokens github.com/TykTechnologies/tyk/gateway diff --git a/cli/linter/linter.go b/cli/linter/linter.go index e743fac595c..fe622dedd36 100644 --- a/cli/linter/linter.go +++ b/cli/linter/linter.go @@ -23,7 +23,7 @@ func Run(schm string, paths []string) (string, []string, error) { schemaLoader := schema.NewBytesLoader([]byte(schm)) var orig map[string]interface{} - f, err := os.Open(conf.OriginalPath) + f, err := os.Open(conf.Private.OriginalPath) if err != nil { return "", nil, err } @@ -46,11 +46,11 @@ func Run(schm string, paths []string) (string, []string, error) { } // ensure it's well formatted and the keys are all lowercase - if err := config.WriteConf(conf.OriginalPath, &conf); err != nil { + if err := config.WriteConf(conf.Private.OriginalPath, &conf); err != nil { return "", nil, err } - return conf.OriginalPath, resultWarns(result), nil + return conf.Private.OriginalPath, resultWarns(result), nil } type stringFormat func(string) bool diff --git a/config/config.go b/config/config.go index 135e2bf713a..f2472fe0ecd 100644 --- a/config/config.go +++ b/config/config.go @@ -557,12 +557,7 @@ func (pwl *PortsWhiteList) Decode(value string) error { // Config is the configuration object used by Tyk to set up various parameters. type Config struct { - // OriginalPath is the path to the config file that is read. If - // none was found, it's the path to the default config file that - // was written. - OriginalPath string `json:"-"` - - // Force your Gateway to work only on a specifc domain name. Can be overriden by API custom domain. + // Force your Gateway to work only on a specific domain name. Can be overridden by API custom domain. HostName string `json:"hostname"` // If your machine has mulitple network devices or IPs you can force the Gateway to use the IP address you want. @@ -1015,6 +1010,8 @@ type Config struct { // Skip TLS verification for JWT JWKs url validation JWTSSLInsecureSkipVerify bool `json:"jwt_ssl_insecure_skip_verify"` + + Private Private `json:"-"` } type TykError struct { @@ -1171,12 +1168,12 @@ func WriteDefault(path string, conf *Config) error { // An error will be returned only if any of the paths existed but was // not a valid config file. func Load(paths []string, conf *Config) error { - var r io.Reader + var r io.ReadCloser for _, path := range paths { f, err := os.Open(path) if err == nil { r = f - conf.OriginalPath = path + conf.Private.OriginalPath = path break } if os.IsNotExist(err) { diff --git a/config/config_test.go b/config/config_test.go index 72df3670aca..29f046b47da 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -113,7 +113,7 @@ func TestConfigFiles(t *testing.T) { if _, err := os.Stat(path2); err == nil { t.Fatalf("Load with no configs wrote too many default config files") } - if conf.OriginalPath != path1 { + if conf.Private.OriginalPath != path1 { t.Fatalf("OriginalPath was not set properly") } @@ -122,7 +122,7 @@ func TestConfigFiles(t *testing.T) { if err := Load(paths, conf); err != nil { t.Fatalf("Load with an existing config errored") } - if conf.OriginalPath != path1 { + if conf.Private.OriginalPath != path1 { t.Fatalf("OriginalPath was not set properly") } @@ -134,7 +134,7 @@ func TestConfigFiles(t *testing.T) { if _, err := os.Stat(path1); err == nil { t.Fatalf("Load with a config wrote a default config file") } - if conf.OriginalPath != path2 { + if conf.Private.OriginalPath != path2 { t.Fatalf("OriginalPath was not set properly") } diff --git a/config/private.go b/config/private.go new file mode 100644 index 00000000000..aad8a7cb474 --- /dev/null +++ b/config/private.go @@ -0,0 +1,22 @@ +package config + +import "time" + +// Private contains configurations which are private, adding it to be part of config without exposing to customers. +type Private struct { + // OAuthTokensPurgeInterval specifies the interval at which lapsed tokens get purged. + OAuthTokensPurgeInterval int `json:"-"` + // OriginalPath is the path to the config file that is read. If + // none was found, it's the path to the default config file that + // was written. + OriginalPath string `json:"-"` +} + +// GetOAuthTokensPurgeInterval returns purge interval for lapsed OAuth tokens. +func (p Private) GetOAuthTokensPurgeInterval() time.Duration { + if p.OAuthTokensPurgeInterval != 0 { + return time.Second * time.Duration(p.OAuthTokensPurgeInterval) + } + + return time.Hour +} diff --git a/config/private_test.go b/config/private_test.go new file mode 100644 index 00000000000..e055368df31 --- /dev/null +++ b/config/private_test.go @@ -0,0 +1,20 @@ +package config + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestPrivate_GetOAuthTokensPurgeInterval(t *testing.T) { + t.Run("default value", func(t *testing.T) { + p := Private{} + assert.Equal(t, time.Hour, p.GetOAuthTokensPurgeInterval()) + }) + + t.Run("custom value", func(t *testing.T) { + p := Private{OAuthTokensPurgeInterval: 5} + assert.Equal(t, time.Second*5, p.GetOAuthTokensPurgeInterval()) + }) +} diff --git a/config/util.go b/config/util.go new file mode 100644 index 00000000000..aeb8850095e --- /dev/null +++ b/config/util.go @@ -0,0 +1,24 @@ +package config + +import ( + "strconv" +) + +// HostAddrs returns a sanitized list of hosts to connect to. +func (config *StorageOptionsConf) HostAddrs() (addrs []string) { + if len(config.Addrs) != 0 { + addrs = config.Addrs + } else { + for h, p := range config.Hosts { + addr := h + ":" + p + addrs = append(addrs, addr) + } + } + + if len(addrs) == 0 && config.Port != 0 { + addr := config.Host + ":" + strconv.Itoa(config.Port) + addrs = append(addrs, addr) + } + + return addrs +} diff --git a/config/util_test.go b/config/util_test.go new file mode 100644 index 00000000000..acb61240ff1 --- /dev/null +++ b/config/util_test.go @@ -0,0 +1,63 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHostAddrs(t *testing.T) { + tests := []struct { + name string + config StorageOptionsConf + want []string + }{ + { + name: "empty", + config: StorageOptionsConf{}, + }, + { + name: "addrs", + config: StorageOptionsConf{ + Addrs: []string{"host1:1234", "host2:5678"}, + }, + want: []string{"host1:1234", "host2:5678"}, + }, + { + name: "hosts map", + config: StorageOptionsConf{ + Hosts: map[string]string{ + "host1": "1234", + "host2": "5678", + }, + }, + want: []string{"host1:1234", "host2:5678"}, + }, + { + name: "addrs and host maps", + config: StorageOptionsConf{ + Addrs: []string{"host1:1234", "host2:5678"}, + Hosts: map[string]string{ + "host3": "1234", + "host4": "5678", + }, + }, + want: []string{"host1:1234", "host2:5678"}, + }, + { + name: "host and port", + config: StorageOptionsConf{ + Host: "localhost", + Port: 6379, + }, + want: []string{"localhost:6379"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.config.HostAddrs() + assert.ElementsMatch(t, tt.want, got) + }) + } +} diff --git a/gateway/api_test.go b/gateway/api_test.go index a6a52bd616d..99844411986 100644 --- a/gateway/api_test.go +++ b/gateway/api_test.go @@ -2043,7 +2043,7 @@ func TestOrgKeyHandler_LastUpdated(t *testing.T) { }...) } -func TestPurgeOAuthClientTokens(t *testing.T) { +func TestPurgeOAuthClientTokensEndpoint(t *testing.T) { conf := func(globalConf *config.Config) { // set tokens to be expired after 1 second globalConf.OauthTokenExpire = 1 diff --git a/gateway/oauth_manager.go b/gateway/oauth_manager.go index 90a870c3246..9ac2d4da0eb 100644 --- a/gateway/oauth_manager.go +++ b/gateway/oauth_manager.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/base64" "encoding/json" - "errors" "fmt" "math" "net/http" @@ -13,18 +12,18 @@ import ( "sync" "time" + "strconv" + "github.com/TykTechnologies/tyk/request" "github.com/hashicorp/go-multierror" "github.com/lonelycode/osin" "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" - "strconv" - "github.com/TykTechnologies/tyk/internal/uuid" "github.com/TykTechnologies/tyk/headers" - tykerrors "github.com/TykTechnologies/tyk/internal/errors" + "github.com/TykTechnologies/tyk/internal/errors" "github.com/TykTechnologies/tyk/storage" "github.com/TykTechnologies/tyk/user" ) @@ -234,8 +233,8 @@ const ( refreshToken = "refresh_token" ) -//in compliance with https://tools.ietf.org/html/rfc7009#section-2.1 -//ToDo: set an authentication mechanism +// in compliance with https://tools.ietf.org/html/rfc7009#section-2.1 +// ToDo: set an authentication mechanism func (o *OAuthHandlers) HandleRevokeToken(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { @@ -1195,10 +1194,22 @@ func (gw *Gateway) purgeLapsedOAuthTokens() error { } redisCluster := &storage.RedisCluster{KeyPrefix: "", HashKeys: false, RedisController: gw.RedisController} + + ok, err := redisCluster.Lock("oauth-purge-lock", time.Minute) + if err != nil { + log.WithError(err).Error("error acquiring lock to purge oauth tokens") + return err + } + + if !ok { + log.Info("oauth tokens purge lock not acquired, purging in background") + return nil + } + keys, err := redisCluster.ScanKeys(oAuthClientTokensKeyPattern) if err != nil { - log.WithError(err).Debug("error while scanning for tokens") + log.WithError(err).Error("error while scanning for tokens") return err } @@ -1224,7 +1235,7 @@ func (gw *Gateway) purgeLapsedOAuthTokens() error { close(errs) combinedErr := &multierror.Error{ - ErrorFormat: tykerrors.Formatter, + ErrorFormat: errors.Formatter, } for err := range errs { diff --git a/gateway/oauth_manager_test.go b/gateway/oauth_manager_test.go index 69fee07a1a6..e5b94ae4c9e 100644 --- a/gateway/oauth_manager_test.go +++ b/gateway/oauth_manager_test.go @@ -6,7 +6,9 @@ package gateway import ( "bytes" + "context" "encoding/json" + "errors" "net/url" "path" "reflect" @@ -14,7 +16,10 @@ import ( "strings" "testing" + "github.com/go-redis/redis/v8" + "github.com/go-redis/redismock/v8" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/TykTechnologies/tyk/config" @@ -64,6 +69,10 @@ const keyRulesWithMetadata = `{ "meta_data": {"key": "meta", "foo": "keybar"} }` +var ( + dummyErr = errors.New("dummy") +) + func buildTestOAuthSpec(apiGens ...func(spec *APISpec)) *APISpec { return BuildAPI(func(spec *APISpec) { spec.APIID = "999999" @@ -1307,51 +1316,229 @@ func TestJSONToFormValues(t *testing.T) { }) } -func TestPurgeOAuthClientTokensEvent(t *testing.T) { +func assertTokensLen(t *testing.T, storageManager storage.Handler, storageKey string, expectedTokensLen int) { + t.Helper() + nowTs := time.Now().Unix() + startScore := strconv.FormatInt(nowTs, 10) + tokens, _, err := storageManager.GetSortedSetRange(storageKey, startScore, "+inf") + assert.NoError(t, err) + assert.Equal(t, expectedTokensLen, len(tokens)) +} + +func TestPurgeOAuthClientTokens(t *testing.T) { + t.Run("event", func(t *testing.T) { + conf := func(globalConf *config.Config) { + // set tokens to be expired after 1 second + globalConf.OauthTokenExpire = 1 + // cleanup tokens older than 1 seconds + globalConf.OauthTokenExpiredRetainPeriod = 1 + } + + ts := StartTest(conf) + defer ts.Close() + + spec := ts.LoadTestOAuthSpec() + + clientID1, clientID2 := uuid.New(), uuid.New() + + ts.createOAuthClientIDAndTokens(t, spec, clientID1) + ts.createOAuthClientIDAndTokens(t, spec, clientID2) + storageKey1, storageKey2 := fmt.Sprintf("%s%s", prefixClientTokens, clientID1), + fmt.Sprintf("%s%s", prefixClientTokens, clientID2) + + storageManager := ts.Gw.getGlobalStorageHandler(generateOAuthPrefix(spec.APIID), false) + storageManager.Connect() + + assertTokensLen(t, storageManager, storageKey1, 3) + assertTokensLen(t, storageManager, storageKey2, 3) + + time.Sleep(time.Second * 2) + + // emit event + + n := Notification{ + Command: OAuthPurgeLapsedTokens, + Gw: ts.Gw, + } + ts.Gw.MainNotifier.Notify(n) + + assertTokensLen(t, storageManager, storageKey1, 0) + assertTokensLen(t, storageManager, storageKey2, 0) + }) + + t.Run("background", func(t *testing.T) { + + conf := func(globalConf *config.Config) { + // set tokens to be expired after 1 second + globalConf.OauthTokenExpire = 1 + // cleanup tokens older than 2 seconds + globalConf.OauthTokenExpiredRetainPeriod = 1 + } + + ts := StartTest(conf) + defer ts.Close() + + spec := ts.LoadTestOAuthSpec() + + clientID1, clientID2 := uuid.New(), uuid.New() + + ts.createOAuthClientIDAndTokens(t, spec, clientID1) + ts.createOAuthClientIDAndTokens(t, spec, clientID2) + storageKey1, storageKey2 := fmt.Sprintf("%s%s", prefixClientTokens, clientID1), + fmt.Sprintf("%s%s", prefixClientTokens, clientID2) + + storageManager := ts.Gw.getGlobalStorageHandler(generateOAuthPrefix(spec.APIID), false) + storageManager.Connect() + + assertTokensLen(t, storageManager, storageKey1, 3) + assertTokensLen(t, storageManager, storageKey2, 3) + + time.Sleep(time.Second * 2) + + assertTokensLen(t, storageManager, storageKey1, 0) + assertTokensLen(t, storageManager, storageKey2, 0) + }) + + t.Run("errors", func(t *testing.T) { + t.Run("lock err", func(t *testing.T) { + gw := Gateway{} + gw.SetConfig(config.Config{ + OauthTokenExpiredRetainPeriod: 1, + }) + db, mock := redismock.NewClientMock() + redisController := storage.NewRedisController(context.Background()) + redisController.MockWith(db, true) + gw.RedisController = redisController + mock.ExpectSetNX("oauth-purge-lock", "1", time.Minute).SetErr(dummyErr) + err := gw.purgeLapsedOAuthTokens() + assert.ErrorIs(t, err, dummyErr) + }) + + t.Run("lock failure", func(t *testing.T) { + gw := Gateway{} + gw.SetConfig(config.Config{ + OauthTokenExpiredRetainPeriod: 1, + }) + db, mock := redismock.NewClientMock() + redisController := storage.NewRedisController(context.Background()) + redisController.MockWith(db, true) + gw.RedisController = redisController + mock.ExpectSetNX("oauth-purge-lock", "1", time.Minute).SetVal(false) + err := gw.purgeLapsedOAuthTokens() + assert.NoError(t, err) + }) + + t.Run("scan keys error", func(t *testing.T) { + gw := Gateway{} + gw.SetConfig(config.Config{ + OauthTokenExpiredRetainPeriod: 1, + }) + db, mock := redismock.NewClientMock() + redisController := storage.NewRedisController(context.Background()) + redisController.MockWith(db, true) + gw.RedisController = redisController + mock.ExpectSetNX("oauth-purge-lock", "1", time.Minute).SetVal(true) + mock.ExpectScan(0, oAuthClientTokensKeyPattern, 0).SetErr(dummyErr) + err := gw.purgeLapsedOAuthTokens() + assert.ErrorIs(t, err, dummyErr) + }) + }) +} + +func BenchmarkPurgeLapsedOAuthTokens(b *testing.B) { conf := func(globalConf *config.Config) { // set tokens to be expired after 1 second globalConf.OauthTokenExpire = 1 // cleanup tokens older than 2 seconds globalConf.OauthTokenExpiredRetainPeriod = 2 + + globalConf.Private.OAuthTokensPurgeInterval = 1 } ts := StartTest(conf) defer ts.Close() - assertTokensLen := func(t *testing.T, storageManager storage.Handler, storageKey string, expectedTokensLen int) { - nowTs := time.Now().Unix() - startScore := strconv.FormatInt(nowTs, 10) - tokens, _, err := storageManager.GetSortedSetRange(storageKey, startScore, "+inf") - assert.NoError(t, err) - assert.Equal(t, expectedTokensLen, len(tokens)) + const ( + apiCount = 10 + clientsCount = 50 + tokensCount = 1000 + ) + + gwConf := ts.Gw.GetConfig() + + cfg := gwConf.Storage + timeout := 5 * time.Second + + opts := &redis.UniversalOptions{ + Addrs: cfg.HostAddrs(), + Username: cfg.Username, + Password: cfg.Password, + DB: cfg.Database, + DialTimeout: timeout, + ReadTimeout: timeout, + WriteTimeout: timeout, + IdleTimeout: 240 * timeout, + PoolSize: 500, } - spec := ts.LoadTestOAuthSpec() + fillZSet := func(client redis.UniversalClient, key string, count int) { + ctx := context.Background() + now := time.Now() + nowTs := now.Unix() + var setMembers []*redis.Z + for k := 0; k < count; k++ { + setMembers = append(setMembers, &redis.Z{ + Score: float64(nowTs - int64(k)), + Member: fmt.Sprintf("dummy-value-%d", k), + }) + } - clientID1, clientID2 := uuid.New(), uuid.New() + // add 10 more tokens to be not expired + for k := 0; k < count/10; k++ { + setMembers = append(setMembers, &redis.Z{ + Score: float64(nowTs + int64((k)*1000)), + Member: fmt.Sprintf("dummy-value-%d", k), + }) + } + client.ZAdd(ctx, key, setMembers...) + } - ts.createOAuthClientIDAndTokens(t, spec, clientID1) - ts.createOAuthClientIDAndTokens(t, spec, clientID2) - storageKey1, storageKey2 := fmt.Sprintf("%s%s", prefixClientTokens, clientID1), - fmt.Sprintf("%s%s", prefixClientTokens, clientID2) + copyZSet := func(client redis.UniversalClient, src, dst string) { + ctx := context.Background() + client.ZRangeStore(ctx, dst, redis.ZRangeArgs{ + Key: src, + Start: "0", + Stop: "+inf", + }) + } - storageManager := ts.Gw.getGlobalStorageHandler(generateOAuthPrefix(spec.APIID), false) - storageManager.Connect() + setup := func(tb testing.TB, client redis.UniversalClient) { + tb.Helper() + now := time.Now() + for i := 0; i < apiCount; i++ { + for j := 0; j < clientsCount; j++ { + //now := time.Now() + dst := fmt.Sprintf("oauth-data.%doauth-client-tokens.%d", i, j) + copyZSet(client, "api", dst) + //tb.Logf("copy zet elapsed %f", time.Since(now).Seconds()) + } - assertTokensLen(t, storageManager, storageKey1, 3) - assertTokensLen(t, storageManager, storageKey2, 3) + } + tb.Logf("setup time elapsed %f", time.Since(now).Seconds()) + } - time.Sleep(time.Second * 3) + client := redis.NewClient(opts.Simple()) // no S1021 + now := time.Now() + fillZSet(client, "api", tokensCount) + b.Logf("fill zet elapsed %f", time.Since(now).Seconds()) - // emit event + b.ReportAllocs() - n := Notification{ - Command: OAuthPurgeLapsedTokens, - Gw: ts.Gw, + for i := 0; i < b.N; i++ { + b.StopTimer() + setup(b, client) + b.StartTimer() + require.NoError(b, ts.Gw.purgeLapsedOAuthTokens()) + b.StopTimer() } - ts.Gw.MainNotifier.Notify(n) - - assertTokensLen(t, storageManager, storageKey1, 0) - assertTokensLen(t, storageManager, storageKey2, 0) - } diff --git a/gateway/redis_signal_handle_config.go b/gateway/redis_signal_handle_config.go index 2a2240b3401..fa4608a5919 100644 --- a/gateway/redis_signal_handle_config.go +++ b/gateway/redis_signal_handle_config.go @@ -128,7 +128,7 @@ func sanitizeConfig(mc map[string]interface{}) map[string]interface{} { } func (gw *Gateway) getExistingConfig() (map[string]interface{}, error) { - f, err := os.Open(gw.GetConfig().OriginalPath) + f, err := os.Open(gw.GetConfig().Private.OriginalPath) if err != nil { return nil, err } diff --git a/gateway/server.go b/gateway/server.go index 72510cd04ba..17dbe4355e5 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -19,19 +19,20 @@ import ( "strconv" "strings" "sync" + "time" "github.com/TykTechnologies/tyk/internal/crypto" "github.com/TykTechnologies/tyk/internal/httputil" "sync/atomic" textTemplate "text/template" - "time" "github.com/TykTechnologies/again" "github.com/TykTechnologies/drl" gas "github.com/TykTechnologies/goautosocket" "github.com/TykTechnologies/gorpc" "github.com/TykTechnologies/goverify" + "github.com/TykTechnologies/tyk/internal/scheduler" logstashHook "github.com/bshuster-repo/logrus-logstash-hook" "github.com/evalphobia/logrus_sentry" graylogHook "github.com/gemnasium/logrus-graylog-hook" @@ -1551,8 +1552,10 @@ func writeProfiles() { } func (gw *Gateway) start() { + conf := gw.GetConfig() + // Set up a default org manager so we can traverse non-live paths - if !gw.GetConfig().SupressDefaultOrgStore { + if !conf.SupressDefaultOrgStore { mainLog.Debug("Initialising default org store") gw.DefaultOrgStore.Init(gw.getGlobalStorageHandler("orgkey.", false)) //DefaultQuotaStore.Init(getGlobalStorageHandler(CloudHandler, "orgkey.", false)) @@ -1560,11 +1563,16 @@ func (gw *Gateway) start() { } // Start listening for reload messages - if !gw.GetConfig().SuppressRedisSignalReload { + if !conf.SuppressRedisSignalReload { go gw.startPubSubLoop() } - conf := gw.GetConfig() + purgeInterval := conf.Private.GetOAuthTokensPurgeInterval() + purgeJob := scheduler.NewJob("purge-oauth-tokens", gw.purgeLapsedOAuthTokens, purgeInterval) + + oauthTokensPurger := scheduler.NewScheduler(log) + go oauthTokensPurger.Start(gw.ctx, purgeJob) + if slaveOptions := conf.SlaveOptions; slaveOptions.UseRPC { mainLog.Debug("Starting RPC reload listener") gw.RPCListener = RPCStorageHandler{ diff --git a/go.mod b/go.mod index c57865f6b7c..4cc762f8661 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,11 @@ require ( github.com/frankban/quicktest v1.11.0 // indirect github.com/gemnasium/logrus-graylog-hook v2.0.7+incompatible github.com/getsentry/raven-go v0.2.0 // indirect - github.com/go-redis/redis/v8 v8.3.1 + github.com/go-redis/redis/v8 v8.11.5 + github.com/go-redis/redismock/v8 v8.11.5 github.com/gocraft/health v0.0.0-20170925182251-8675af27fef0 github.com/gofrs/uuid v3.3.0+incompatible - github.com/golang/protobuf v1.4.2 + github.com/golang/protobuf v1.5.2 github.com/google/btree v1.0.0 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/gorilla/mux v1.8.0 @@ -49,7 +50,6 @@ require ( github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-retryablehttp v0.6.7 // indirect - github.com/hashicorp/go-version v1.1.0 github.com/hashicorp/memberlist v0.1.6 // indirect github.com/hashicorp/serf v0.8.6 // indirect github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086 @@ -94,7 +94,6 @@ require ( golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e golang.org/x/net v0.0.0-20211209124913-491a49abca63 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20211013075003-97ac67df715c // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect google.golang.org/appengine v1.6.1 // indirect google.golang.org/grpc v1.29.1 diff --git a/go.sum b/go.sum index 0630727129d..20570574d9c 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,9 @@ github.com/certifi/gocertifi v0.0.0-20190905060710-a5e0173ced67/go.mod h1:GJKEex github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= @@ -160,9 +163,12 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-redis/redis/v8 v8.3.1 h1:jEPCgHQopfNaABun3NVN9pv2K7RjstY/7UJD6UEKFEY= -github.com/go-redis/redis/v8 v8.3.1/go.mod h1:a2xkpBM7NJUN5V5kiF46X5Ltx4WeXJ9757X/ScKUBdE= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-redis/redismock/v8 v8.11.5 h1:RJFIiua58hrBrSpXhnGX3on79AU3S271H4ZhRI1wyVo= +github.com/go-redis/redismock/v8 v8.11.5/go.mod h1:UaAU9dEe1C+eGr+FHV5prCWIt0hafyPWbGMEWE0UWdA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= @@ -203,6 +209,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= @@ -215,9 +224,11 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -271,7 +282,6 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -298,6 +308,7 @@ github.com/huandu/xstrings v1.2.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -427,17 +438,23 @@ github.com/nsf/jsondiff v0.0.0-20210303162244-6ea32392771e h1:S+/ptYdZtpK/MDstwC github.com/nsf/jsondiff v0.0.0-20210303162244-6ea32392771e/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= -github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= -github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= @@ -543,7 +560,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4= @@ -588,8 +604,6 @@ github.com/xenolf/lego v0.3.2-0.20170618175828-28ead50ff1ca/go.mod h1:fwiGnfsIjG github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v0.13.0 h1:2isEnyzjjJZq6r2EKMsFj4TxiQiexsM04AVhwbR/oBA= -go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -648,6 +662,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -680,19 +695,20 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8= -golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -722,6 +738,7 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -751,6 +768,9 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -780,6 +800,8 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -794,5 +816,3 @@ rsc.io/letsencrypt v0.0.2 h1:CWRvaqcmyyWMhhhGes73TvuIjf7O3Crq6F+Xid/cWNI= rsc.io/letsencrypt v0.0.2/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/internal/errors/errors.go b/internal/errors/errors.go index 4faa273d4ae..70bd562ca6a 100644 --- a/internal/errors/errors.go +++ b/internal/errors/errors.go @@ -1,6 +1,15 @@ package errors -import "strings" +import ( + "errors" + "strings" +) + +var ( + New = errors.New + Is = errors.Is + Unwrap = errors.Unwrap +) func Formatter(errs []error) string { var result strings.Builder diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go new file mode 100644 index 00000000000..e97aa23a92c --- /dev/null +++ b/internal/scheduler/scheduler.go @@ -0,0 +1,105 @@ +// Package scheduler provides a simple job scheduling utility with support +// for running periodic tasks and graceful shutdown. +package scheduler + +import ( + "context" + "errors" + "sync" + "time" + + "github.com/sirupsen/logrus" +) + +// Break is an error used to indicate the need to break the scheduler loop. +// It's an internal mechanism for stopping a job's execution within the scheduler. +var Break = errors.New("internal: break scheduler loop") + +// Job represents a task that can be scheduled. Each Job has a Name, a Run function +// that performs the task, and an Interval that determines how often the task should run. +type Job struct { + Name string + Run func() error + Interval time.Duration +} + +// NewJob creates and returns a new Job with the specified name, task function, and interval. +func NewJob(name string, run func() error, interval time.Duration) *Job { + return &Job{ + Name: name, + Run: run, + Interval: interval, + } +} + +// Scheduler is responsible for executing Jobs at specified intervals. +type Scheduler struct { + logger *logrus.Logger + + mustBreak bool + stop chan bool + stopOnce sync.Once +} + +// NewScheduler creates and returns a new Scheduler with the specified logger. +func NewScheduler(logger *logrus.Logger) *Scheduler { + return &Scheduler{ + logger: logger, + stop: make(chan bool), + } +} + +// Logger creates and returns a logrus Entry with the scheduler prefix. +func (s *Scheduler) Logger() *logrus.Entry { + return s.logger.WithField("prefix", "scheduler") +} + +// Start begins the execution of the provided Job within the context of the Scheduler. +// It schedules the Job's Run function to be called at its specified interval. The job +// can be stopped via context cancellation, calling Close, or when the job returns the +// Break error. +func (s *Scheduler) Start(ctx context.Context, job *Job) { + tick := time.NewTicker(job.Interval) + + defer func() { + tick.Stop() + }() + + for { + logger := s.Logger().WithField("name", job.Name) + + err := job.Run() + + switch { + case errors.Is(err, Break): + s.mustBreak = true + logger.Info("job scheduler stopping") + case err != nil: + logger.WithError(err).Errorf("job run error") + default: + logger.Info("job run successful") + } + + if s.mustBreak { + break + } + + select { + case <-s.stop: + return + case <-ctx.Done(): + s.Close() + return + case <-tick.C: + } + } +} + +// Close gracefully stops the execution of any running Jobs in the Scheduler. +// It is safe to call multiple times and is concurrent-safe. +func (s *Scheduler) Close() error { + s.stopOnce.Do(func() { + close(s.stop) + }) + return nil +} diff --git a/internal/scheduler/scheduler_test.go b/internal/scheduler/scheduler_test.go new file mode 100644 index 00000000000..a3c98bfb97f --- /dev/null +++ b/internal/scheduler/scheduler_test.go @@ -0,0 +1,76 @@ +package scheduler_test + +import ( + "context" + "io" + "testing" + "time" + + logrus "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + + "github.com/TykTechnologies/tyk/internal/scheduler" +) + +func TestScheduler_Break(t *testing.T) { + logger, _ := logrus.NewNullLogger() + + s := scheduler.NewScheduler(logger) + + assert.NotEmpty(t, s) + + job := scheduler.NewJob("test", func() error { + return scheduler.Break + }, 1) + + s.Start(context.Background(), job) + + assert.NotNil(t, s) +} + +func TestScheduler_Close(t *testing.T) { + logger, _ := logrus.NewNullLogger() + + s := scheduler.NewScheduler(logger) + defer s.Close() + + job := scheduler.NewJob("test", func() error { + return nil + }, 1) + + go s.Start(context.Background(), job) + + assert.NotNil(t, s) +} + +func TestScheduler_Job_Errors(t *testing.T) { + logger, _ := logrus.NewNullLogger() + + testcases := []struct { + name string + err error + }{ + {name: "no error", err: nil}, + {name: "error", err: io.EOF}, + {name: "cancelled", err: context.Canceled}, + {name: "break", err: scheduler.Break}, + } + + for _, tc := range testcases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + job := scheduler.NewJob("test", func() error { + return tc.err + }, 1) + + runner := scheduler.NewScheduler(logger) + go runner.Start(ctx, job) + + time.Sleep(time.Millisecond) + }) + } +} diff --git a/storage/redis_cluster.go b/storage/redis_cluster.go index e37c70599fa..d3763e471e5 100644 --- a/storage/redis_cluster.go +++ b/storage/redis_cluster.go @@ -96,22 +96,8 @@ func NewRedisClusterPool(isCache, isAnalytics bool, conf config.Config) redis.Un return client } -func getRedisAddrs(config config.StorageOptionsConf) (addrs []string) { - if len(config.Addrs) != 0 { - addrs = config.Addrs - } else { - for h, p := range config.Hosts { - addr := h + ":" + p - addrs = append(addrs, addr) - } - } - - if len(addrs) == 0 && config.Port != 0 { - addr := config.Host + ":" + strconv.Itoa(config.Port) - addrs = append(addrs, addr) - } - - return addrs +func getRedisAddrs(conf config.StorageOptionsConf) (addrs []string) { + return conf.HostAddrs() } func clusterConnectionIsOpen(cluster *RedisCluster) bool { @@ -375,6 +361,24 @@ func (r *RedisCluster) SetRawKey(keyName, session string, timeout int64) error { return nil } +// Lock implements a distributed lock in a cluster. +func (r *RedisCluster) Lock(key string, timeout time.Duration) (bool, error) { + if err := r.up(); err != nil { + return false, err + } + singleton, err := r.singleton() + if err != nil { + return false, err + } + + res := singleton.SetNX(r.RedisController.ctx, key, "1", timeout) + if err := res.Err(); err != nil { + log.WithError(err).Error("Error trying to set value") + return false, err + } + return res.Val(), nil +} + // Decrement will decrement a key in redis func (r *RedisCluster) Decrement(keyName string) { keyName = r.fixKey(keyName) diff --git a/storage/redis_cluster_test.go b/storage/redis_cluster_test.go index e41127b90e2..81e34622add 100644 --- a/storage/redis_cluster_test.go +++ b/storage/redis_cluster_test.go @@ -2,13 +2,16 @@ package storage import ( "context" + "errors" "testing" "time" "github.com/go-redis/redis/v8" - "github.com/TykTechnologies/tyk/config" + "github.com/go-redis/redismock/v8" "github.com/stretchr/testify/assert" + + "github.com/TykTechnologies/tyk/config" ) var rc RedisController @@ -200,3 +203,85 @@ func TestCheckIsOpen(t *testing.T) { assert.NoError(t, err) } + +func TestLock(t *testing.T) { + t.Run("redis down", func(t *testing.T) { + db, _ := redismock.NewClientMock() + redisCluster := &RedisCluster{ + RedisController: &RedisController{ + ctx: context.Background(), + singlePool: db, + }, + } + redisCluster.RedisController.redisUp.Store(false) + + ok, err := redisCluster.Lock("lock-key", time.Second) + assert.Error(t, err) + assert.False(t, ok) + }) + + t.Run("redis not configured", func(t *testing.T) { + redisCluster := &RedisCluster{ + RedisController: &RedisController{ + ctx: context.Background(), + }, + } + redisCluster.RedisController.redisUp.Store(true) + + ok, err := redisCluster.Lock("lock-key", time.Second) + assert.Contains(t, err.Error(), "Error trying to get singleton instance") + assert.False(t, ok) + }) + + t.Run("lock success", func(t *testing.T) { + db, mock := redismock.NewClientMock() + mock.ExpectSetNX("lock-key", "1", time.Second).SetVal(true) + + redisCluster := &RedisCluster{ + RedisController: &RedisController{ + ctx: context.Background(), + singlePool: db, + }, + } + redisCluster.RedisController.redisUp.Store(true) + + ok, err := redisCluster.Lock("lock-key", time.Second) + assert.NoError(t, err) + assert.True(t, ok) + }) + + t.Run("lock failure", func(t *testing.T) { + db, mock := redismock.NewClientMock() + mock.ExpectSetNX("lock-key", "1", time.Second).SetVal(false) + + redisCluster := &RedisCluster{ + RedisController: &RedisController{ + ctx: context.Background(), + singlePool: db, + }, + } + redisCluster.RedisController.redisUp.Store(true) + + ok, err := redisCluster.Lock("lock-key", time.Second) + assert.NoError(t, err) + assert.False(t, ok) + }) + + t.Run("lock error", func(t *testing.T) { + db, mock := redismock.NewClientMock() + dummyErr := errors.New("dummy") + mock.ExpectSetNX("lock-key", "1", time.Second).SetErr(dummyErr) + + redisCluster := &RedisCluster{ + RedisController: &RedisController{ + ctx: context.Background(), + singlePool: db, + }, + } + redisCluster.RedisController.redisUp.Store(true) + + ok, err := redisCluster.Lock("lock-key", time.Second) + assert.Equal(t, dummyErr, err) + assert.False(t, ok) + }) +} diff --git a/storage/redis_controller.go b/storage/redis_controller.go index 79b0f659a4c..ab57ca10d86 100644 --- a/storage/redis_controller.go +++ b/storage/redis_controller.go @@ -241,3 +241,11 @@ func (rc *RedisController) establishConnection(v *RedisCluster, conf config.Conf } return clusterConnectionIsOpen(v) } + +// MockWith is used to mock redis controller with a redis client. +func (rc *RedisController) MockWith(client redis.UniversalClient, redisUp bool) { + rc.singlePool = client + rc.singleAnalyticsPool = client + rc.singleAnalyticsPool = client + rc.redisUp.Store(redisUp) +} From afa4a53cceecc648dec7887dddee3df4cd912bc4 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Mon, 8 Jan 2024 15:32:56 +0100 Subject: [PATCH 33/33] Remove del-env, config docs (#5931) As per the https://tyktech.atlassian.net/browse/SYSE-292 policy, delete old workflows for 4-lts; Related to: https://github.com/TykTechnologies/tyk-docs/pull/3831 Co-authored-by: Tit Petric --- .github/workflows/del-env.yml | 26 ------------------------ .github/workflows/update-config-docs.yml | 23 --------------------- 2 files changed, 49 deletions(-) delete mode 100644 .github/workflows/del-env.yml delete mode 100644 .github/workflows/update-config-docs.yml diff --git a/.github/workflows/del-env.yml b/.github/workflows/del-env.yml deleted file mode 100644 index d4ee129ad97..00000000000 --- a/.github/workflows/del-env.yml +++ /dev/null @@ -1,26 +0,0 @@ - - -# Generated by: tyk-ci/wf-gen -# Generated on: Friday 04 March 2022 11:40:32 AM UTC - -# Generation commands: -# ./pr.zsh -repos tyk -base td-883-test -branch td-883-test -title Sync from latest releng templates -# m4 -E -DxREPO=tyk - -name: Retiring dev env - -on: - delete: - branches: - - feature/* - - integration/* - -jobs: - retire: - runs-on: ubuntu-latest - - steps: - - name: Tell gromit about deleted branch - run: | - curl -fsSL -H "Authorization: ${{secrets.GROMIT_TOKEN}}" "https://domu-kun.cloud.tyk.io/gromit/env/${GITHUB_REF##*/}" \ - -X DELETE diff --git a/.github/workflows/update-config-docs.yml b/.github/workflows/update-config-docs.yml deleted file mode 100644 index 816324ba819..00000000000 --- a/.github/workflows/update-config-docs.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Keep the docs on tyk-docs in sync with this branch's docs - -name: Update Config docs - -on: - push: - branches: - - master - - release-** - paths: - - config/config.go - -jobs: - sync: - name: tyk-config-docs - runs-on: ubuntu-latest - steps: - - uses: peter-evans/repository-dispatch@v1 - with: - token: ${{ secrets.ORG_GH_TOKEN }} - repository: TykTechnologies/tyk-docs - event-type: tyk-config-docs - client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}","repo":"gateway","branch":"${{github.ref_name}}"}'