Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bbc35e5be |
@@ -17,7 +17,7 @@ jobs:
|
|||||||
name: lint
|
name: lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v4
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ on:
|
|||||||
- v*
|
- v*
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
name: Run Snifftest
|
name: Run Snifftest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v4
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
id-token: 'write'
|
id-token: 'write'
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
id-token: 'write'
|
id-token: 'write'
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.18'
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ Expected output:
|
|||||||
trufflehog s3 --bucket=<bucket name> --only-verified
|
trufflehog s3 --bucket=<bucket name> --only-verified
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### FAQ
|
||||||
|
|
||||||
|
+ All I see is `🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷` and the program exits, what gives?
|
||||||
|
+ That means no secrets were detected
|
||||||
|
+ Why is the scan is taking a long time when I scan a GitHub org
|
||||||
|
+ Unauthenticated GitHub scans have rate limits. To improve your rate limits, include the `--token` flag with a personal access token
|
||||||
|
+ It says a private key was verified, what does that mean?
|
||||||
|
+ Check out our Driftwood blog post to learn how to do this, in short we've confirmed the key can be used live for SSH or SSL [Blog post](https://trufflesecurity.com/blog/driftwood-know-if-private-keys-are-sensitive/)
|
||||||
|
|
||||||
|
|
||||||
### Example 5: Scan a Github Repo using SSH authentication in docker
|
### Example 5: Scan a Github Repo using SSH authentication in docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -96,22 +106,6 @@ docker run --rm -v "$HOME/.ssh:/root/.ssh:ro" trufflesecurity/trufflehog:latest
|
|||||||
trufflehog filesystem path/to/file1.txt path/to/file2.txt path/to/dir
|
trufflehog filesystem path/to/file1.txt path/to/file2.txt path/to/dir
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example 7: Scan GCS buckets for verified secrets.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
trufflehog gcs --project-id=<project-ID> --cloud-environment --only-verified
|
|
||||||
```
|
|
||||||
|
|
||||||
### FAQ
|
|
||||||
|
|
||||||
+ All I see is `🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷` and the program exits, what gives?
|
|
||||||
+ That means no secrets were detected
|
|
||||||
+ Why is the scan is taking a long time when I scan a GitHub org
|
|
||||||
+ Unauthenticated GitHub scans have rate limits. To improve your rate limits, include the `--token` flag with a personal access token
|
|
||||||
+ It says a private key was verified, what does that mean?
|
|
||||||
+ Check out our Driftwood blog post to learn how to do this, in short we've confirmed the key can be used live for SSH or SSL [Blog post](https://trufflesecurity.com/blog/driftwood-know-if-private-keys-are-sensitive/)
|
|
||||||
|
|
||||||
|
|
||||||
# What's new in v3?
|
# What's new in v3?
|
||||||
|
|
||||||
TruffleHog v3 is a complete rewrite in Go with many new powerful features.
|
TruffleHog v3 is a complete rewrite in Go with many new powerful features.
|
||||||
@@ -182,7 +176,6 @@ TruffleHog has a sub-command for each source of data that you may want to scan:
|
|||||||
- filesystem (files and directories)
|
- filesystem (files and directories)
|
||||||
- syslog
|
- syslog
|
||||||
- circleci
|
- circleci
|
||||||
- GCS (Google Cloud Storage)
|
|
||||||
- stdin (coming soon)
|
- stdin (coming soon)
|
||||||
|
|
||||||
Each subcommand can have options that you can see with the `--help` flag provided to the sub command:
|
Each subcommand can have options that you can see with the `--help` flag provided to the sub command:
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ inputs:
|
|||||||
default: ''
|
default: ''
|
||||||
description: Extra args to be passed to the trufflehog cli.
|
description: Extra args to be passed to the trufflehog cli.
|
||||||
required: false
|
required: false
|
||||||
outputs:
|
|
||||||
results:
|
|
||||||
description: 'Trufflehog scan results'
|
|
||||||
branding:
|
branding:
|
||||||
icon: "shield"
|
icon: "shield"
|
||||||
color: "green"
|
color: "green"
|
||||||
@@ -35,5 +32,4 @@ runs:
|
|||||||
- ${{ inputs.head }}
|
- ${{ inputs.head }}
|
||||||
- --fail
|
- --fail
|
||||||
- --no-update
|
- --no-update
|
||||||
- --github-actions
|
|
||||||
- ${{ inputs.extra_args }}
|
- ${{ inputs.extra_args }}
|
||||||
|
|||||||
+1
-2
@@ -3,5 +3,4 @@
|
|||||||
# Parse the last argument into an array of extra_args.
|
# Parse the last argument into an array of extra_args.
|
||||||
mapfile -t extra_args < <(bash -c "for arg in ${*: -1}; do echo \$arg; done")
|
mapfile -t extra_args < <(bash -c "for arg in ${*: -1}; do echo \$arg; done")
|
||||||
|
|
||||||
results=$(/usr/bin/trufflehog "${@: 1: $#-1}" "${extra_args[@]}" | tee /dev/tty)
|
/usr/bin/trufflehog "${@: 1: $#-1}" "${extra_args[@]}"
|
||||||
echo "results=$results" >> $GITHUB_OUTPUT
|
|
||||||
@@ -10,22 +10,21 @@ replace github.com/gitleaks/go-gitdiff => github.com/trufflesecurity/go-gitdiff
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/secretmanager v1.10.0
|
cloud.google.com/go/secretmanager v1.10.0
|
||||||
cloud.google.com/go/storage v1.30.1
|
|
||||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
|
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
|
||||||
github.com/TheZeroSlave/zapsentry v1.14.0
|
github.com/TheZeroSlave/zapsentry v1.14.0
|
||||||
github.com/aws/aws-sdk-go v1.44.83
|
github.com/aws/aws-sdk-go v1.44.83
|
||||||
github.com/bill-rich/disk-buffer-reader v0.1.7
|
github.com/bill-rich/disk-buffer-reader v0.1.7
|
||||||
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c
|
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c
|
||||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb
|
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb
|
||||||
github.com/bradleyfalzon/ghinstallation/v2 v2.2.0
|
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
|
||||||
github.com/crewjam/rfc5424 v0.1.0
|
github.com/crewjam/rfc5424 v0.1.0
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3
|
github.com/denisenkom/go-mssqldb v0.12.3
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.9.1
|
github.com/envoyproxy/protoc-gen-validate v0.9.1
|
||||||
github.com/fatih/color v1.15.0
|
github.com/fatih/color v1.13.0
|
||||||
github.com/felixge/fgprof v0.9.3
|
github.com/felixge/fgprof v0.9.3
|
||||||
github.com/getsentry/sentry-go v0.19.0
|
github.com/getsentry/sentry-go v0.18.0
|
||||||
github.com/go-errors/errors v1.4.2
|
github.com/go-errors/errors v1.4.2
|
||||||
github.com/go-git/go-git/v5 v5.6.1
|
github.com/go-git/go-git/v5 v5.5.2
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4
|
github.com/go-ldap/ldap/v3 v3.4.4
|
||||||
github.com/go-logr/logr v1.2.3
|
github.com/go-logr/logr v1.2.3
|
||||||
github.com/go-logr/zapr v1.2.3
|
github.com/go-logr/zapr v1.2.3
|
||||||
@@ -35,7 +34,6 @@ require (
|
|||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/google/go-github/v42 v42.0.0
|
github.com/google/go-github/v42 v42.0.0
|
||||||
github.com/googleapis/gax-go/v2 v2.8.0
|
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.2
|
github.com/hashicorp/go-retryablehttp v0.7.2
|
||||||
github.com/jlaffaye/ftp v0.1.0
|
github.com/jlaffaye/ftp v0.1.0
|
||||||
@@ -45,34 +43,30 @@ require (
|
|||||||
github.com/lib/pq v1.10.7
|
github.com/lib/pq v1.10.7
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7
|
github.com/mholt/archiver/v4 v4.0.0-alpha.7
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
|
||||||
github.com/paulbellamy/ratecounter v0.2.0
|
github.com/paulbellamy/ratecounter v0.2.0
|
||||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9
|
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/rabbitmq/amqp091-go v1.8.0
|
github.com/rabbitmq/amqp091-go v1.7.0
|
||||||
github.com/sergi/go-diff v1.3.1
|
github.com/sergi/go-diff v1.3.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502
|
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502
|
||||||
github.com/xanzy/go-gitlab v0.81.0
|
github.com/xanzy/go-gitlab v0.80.2
|
||||||
go.mongodb.org/mongo-driver v1.11.3
|
go.mongodb.org/mongo-driver v1.11.2
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/crypto v0.7.0
|
golang.org/x/crypto v0.6.0
|
||||||
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7
|
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7
|
||||||
golang.org/x/oauth2 v0.6.0
|
golang.org/x/oauth2 v0.5.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/text v0.8.0
|
golang.org/x/text v0.7.0
|
||||||
google.golang.org/api v0.114.0
|
google.golang.org/protobuf v1.28.1
|
||||||
google.golang.org/protobuf v1.30.0
|
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||||
gopkg.in/h2non/gock.v1 v1.1.2
|
gopkg.in/h2non/gock.v1 v1.1.2
|
||||||
sigs.k8s.io/yaml v1.3.0
|
sigs.k8s.io/yaml v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.110.0 // indirect
|
cloud.google.com/go/compute v1.12.1 // indirect
|
||||||
cloud.google.com/go/compute v1.18.0 // indirect
|
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/iam v0.8.0 // indirect
|
||||||
cloud.google.com/go/iam v0.12.0 // indirect
|
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
|
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
||||||
@@ -82,8 +76,8 @@ require (
|
|||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
|
||||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
github.com/Microsoft/go-winio v0.5.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||||
@@ -95,19 +89,19 @@ require (
|
|||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||||
github.com/go-git/gcfg v1.5.0 // indirect
|
github.com/go-git/gcfg v1.5.0 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.4.1 // indirect
|
github.com/go-git/go-billy/v5 v5.4.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-github/v50 v50.1.0 // indirect
|
github.com/google/go-github/v45 v45.2.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
@@ -120,14 +114,15 @@ require (
|
|||||||
github.com/klauspost/compress v1.15.11 // indirect
|
github.com/klauspost/compress v1.15.11 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
|
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/onsi/gomega v1.23.0 // indirect
|
github.com/onsi/gomega v1.23.0 // indirect
|
||||||
|
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.2.3 // indirect
|
||||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 // indirect
|
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
github.com/skeema/knownhosts v1.1.0 // indirect
|
||||||
@@ -142,15 +137,15 @@ require (
|
|||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.7.0 // indirect
|
||||||
golang.org/x/net v0.8.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.6.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.3.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
google.golang.org/api v0.103.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect
|
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c // indirect
|
||||||
google.golang.org/grpc v1.53.0 // indirect
|
google.golang.org/grpc v1.51.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
|
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||||
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
|
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk=
|
||||||
cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE=
|
cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE=
|
||||||
cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY=
|
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
|
||||||
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
|
|
||||||
cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=
|
cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=
|
||||||
cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
|
cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
|
||||||
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
|
|
||||||
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||||
@@ -38,12 +35,12 @@ github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzS
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
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/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
|
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||||
github.com/TheZeroSlave/zapsentry v1.14.0 h1:z6H0lIyKVpdXsP5K8J11b4/+V+QCDLDslZmtXsnduMk=
|
github.com/TheZeroSlave/zapsentry v1.14.0 h1:z6H0lIyKVpdXsP5K8J11b4/+V+QCDLDslZmtXsnduMk=
|
||||||
github.com/TheZeroSlave/zapsentry v1.14.0/go.mod h1:0hUR1Et5tSroEYhWOZcxE2iBqcFkuG7jGGlUmOA7XAs=
|
github.com/TheZeroSlave/zapsentry v1.14.0/go.mod h1:0hUR1Et5tSroEYhWOZcxE2iBqcFkuG7jGGlUmOA7XAs=
|
||||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||||
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/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-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||||
@@ -64,8 +61,8 @@ github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c h1:tSME5FDS02q
|
|||||||
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c/go.mod h1:+sCc6hztur+oZCLOsNk6wCCy+GLrnSNHSRmTnnL+8iQ=
|
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c/go.mod h1:+sCc6hztur+oZCLOsNk6wCCy+GLrnSNHSRmTnnL+8iQ=
|
||||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb h1:9v7Bzlg+1EBYi2IYcUmOwHReBEfqBbYIj3ZCi9cIe1Q=
|
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb h1:9v7Bzlg+1EBYi2IYcUmOwHReBEfqBbYIj3ZCi9cIe1Q=
|
||||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb/go.mod h1:EkOqCuelvo7DY8vCOoZ09p7pHvAK9B1PHI9GeM4Rdxc=
|
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb/go.mod h1:EkOqCuelvo7DY8vCOoZ09p7pHvAK9B1PHI9GeM4Rdxc=
|
||||||
github.com/bradleyfalzon/ghinstallation/v2 v2.2.0 h1:AVvVU33rE8wdTS1aNnenwpigEBA9mvzI5OhjhZfH/LU=
|
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 h1:5+NghM1Zred9Z078QEZtm28G/kfDfZN/92gkDlLwGVA=
|
||||||
github.com/bradleyfalzon/ghinstallation/v2 v2.2.0/go.mod h1:xo3iIfK0lDKECe0s19nbxT0KKvk7LsrGc4NxR5ckKMA=
|
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0/go.mod h1:Xg3xPRN5Mcq6GDqeUVhFbjEWMb4JHCyWEeeBGEYQoTU=
|
||||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
@@ -97,15 +94,15 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=
|
github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
|
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
|
||||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
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 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM=
|
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
|
||||||
github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE=
|
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
|
||||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
||||||
@@ -115,12 +112,12 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
|
|||||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE=
|
||||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||||
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
|
github.com/go-git/go-git/v5 v5.5.2 h1:v8lgZa5k9ylUw+OR/roJHTxR4QItsNFI5nKtAXFuynw=
|
||||||
github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8=
|
github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4BlxtH7OjI=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
|
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
|
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
@@ -144,8 +141,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
|
|||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
@@ -166,8 +163,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
|||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
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.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
@@ -179,24 +176,22 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.2/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.3/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.5/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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec=
|
github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec=
|
||||||
github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg=
|
github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg=
|
||||||
github.com/google/go-github/v50 v50.1.0 h1:hMUpkZjklC5GJ+c3GquSqOP/T4BNsB7XohaPhtMOzRk=
|
github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=
|
||||||
github.com/google/go-github/v50 v50.1.0/go.mod h1:Ev4Tre8QoKiolvbpOSG3FIi4Mlon3S2Nt9W5JYqKiwA=
|
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
github.com/google/uuid v1.1.2/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/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||||
github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
@@ -251,18 +246,19 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
|||||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
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-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
|
||||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7 h1:xzByj8G8tj0Oq7ZYYU4+ixL/CVb5ruWCm0EZQ1PjOkE=
|
github.com/mholt/archiver/v4 v4.0.0-alpha.7 h1:xzByj8G8tj0Oq7ZYYU4+ixL/CVb5ruWCm0EZQ1PjOkE=
|
||||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7/go.mod h1:Fs8qUkO74HHaidabihzYephJH8qmGD/nCP6tE5xC9BM=
|
github.com/mholt/archiver/v4 v4.0.0-alpha.7/go.mod h1:Fs8qUkO74HHaidabihzYephJH8qmGD/nCP6tE5xC9BM=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
|
|
||||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
@@ -283,8 +279,6 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
|
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
|
||||||
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
|
||||||
github.com/paulbellamy/ratecounter v0.2.0 h1:2L/RhJq+HA8gBQImDXtLPrDXK5qAj6ozWVK/zFXVJGs=
|
github.com/paulbellamy/ratecounter v0.2.0 h1:2L/RhJq+HA8gBQImDXtLPrDXK5qAj6ozWVK/zFXVJGs=
|
||||||
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
||||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8=
|
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8=
|
||||||
@@ -292,8 +286,8 @@ github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.
|
|||||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
|
||||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 h1:+/+DxvQaYifJ+grD4klzrS5y+KJXldn/2YTl5JG+vZ8=
|
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 h1:+/+DxvQaYifJ+grD4klzrS5y+KJXldn/2YTl5JG+vZ8=
|
||||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
|
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
|
||||||
@@ -303,8 +297,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rabbitmq/amqp091-go v1.8.0 h1:GBFy5PpLQ5jSVVSYv8ecHGqeX7UTLYR4ItQbDCss9MM=
|
github.com/rabbitmq/amqp091-go v1.7.0 h1:V5CF5qPem5OGSnEo8BoSbsDGwejg6VUJsKEdneaoTUo=
|
||||||
github.com/rabbitmq/amqp091-go v1.8.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
|
github.com/rabbitmq/amqp091-go v1.7.0/go.mod h1:wfClAtY0C7bOHxd3GjmF26jEHn+rR/0B3+YV+Vn9/NI=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
@@ -342,8 +336,8 @@ github.com/trufflesecurity/overseer v1.1.7-custom5/go.mod h1:nT9w37AiO1Nop2VhVhN
|
|||||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/xanzy/go-gitlab v0.81.0 h1:ofbhZ5ZY9AjHATWQie4qd2JfncdUmvcSA/zfQB767Dk=
|
github.com/xanzy/go-gitlab v0.80.2 h1:CH1Q7NDklqZllox4ICVF4PwlhQGfPtE+w08Jsb74ZX0=
|
||||||
github.com/xanzy/go-gitlab v0.81.0/go.mod h1:VMbY3JIWdZ/ckvHbQqkyd3iYk2aViKrNIQ23IbFMQDo=
|
github.com/xanzy/go-gitlab v0.80.2/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M=
|
||||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
@@ -355,24 +349,24 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
|
go.mongodb.org/mongo-driver v1.11.2 h1:+1v2rDQUWNcGW7/7E0Jvdz51V38XXxJfhzbV17aNHCw=
|
||||||
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
go.mongodb.org/mongo-driver v1.11.2/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
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/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||||
golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
@@ -383,10 +377,9 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0
|
|||||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
|
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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-20221018205818-5c77f4b2bbd7 h1:lhh9BuEmjIBOdOhMIGSQzdW5LbTtFbUV1k9O/Rlq3SE=
|
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7 h1:lhh9BuEmjIBOdOhMIGSQzdW5LbTtFbUV1k9O/Rlq3SE=
|
||||||
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
@@ -396,10 +389,10 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
|
||||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-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-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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -412,19 +405,18 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/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-20201110031124-69a78807bb2b/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
|
||||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-20181108010431-42b317875d0f/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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -442,6 +434,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/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-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-20191120155948-bd437916bb0e/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-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -450,8 +444,11 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/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-20211216021012-1d35b9e2eb4e/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -460,26 +457,23 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
|
||||||
golang.org/x/text v0.3.0/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.2/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -491,18 +485,16 @@ 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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ=
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
|
||||||
google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
|
|
||||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
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.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
@@ -510,15 +502,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
|||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 h1:khxVcsk/FhnzxMKOyD+TDGwjbEOpcPuIpmafPGFmhMA=
|
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg=
|
||||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.23.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.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
google.golang.org/grpc v1.27.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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-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 v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -530,8 +522,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
|||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
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-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.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
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/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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -560,6 +552,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
|
||||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||||
|
|||||||
@@ -34,19 +34,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cli = kingpin.New("TruffleHog", "TruffleHog is a tool for finding credentials.")
|
cli = kingpin.New("TruffleHog", "TruffleHog is a tool for finding credentials.")
|
||||||
cmd string
|
cmd string
|
||||||
debug = cli.Flag("debug", "Run in debug mode.").Bool()
|
debug = cli.Flag("debug", "Run in debug mode.").Bool()
|
||||||
trace = cli.Flag("trace", "Run in trace mode.").Bool()
|
trace = cli.Flag("trace", "Run in trace mode.").Bool()
|
||||||
profile = cli.Flag("profile", "Enables profiling and sets a pprof and fgprof server on :18066.").Bool()
|
profile = cli.Flag("profile", "Enables profiling and sets a pprof and fgprof server on :18066.").Bool()
|
||||||
jsonOut = cli.Flag("json", "Output in JSON format.").Short('j').Bool()
|
jsonOut = cli.Flag("json", "Output in JSON format.").Short('j').Bool()
|
||||||
jsonLegacy = cli.Flag("json-legacy", "Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources.").Bool()
|
jsonLegacy = cli.Flag("json-legacy", "Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources.").Bool()
|
||||||
gitHubActionsFormat = cli.Flag("github-actions", "Output in GitHub Actions format.").Bool()
|
concurrency = cli.Flag("concurrency", "Number of concurrent workers.").Default(strconv.Itoa(runtime.NumCPU())).Int()
|
||||||
concurrency = cli.Flag("concurrency", "Number of concurrent workers.").Default(strconv.Itoa(runtime.NumCPU())).Int()
|
noVerification = cli.Flag("no-verification", "Don't verify the results.").Bool()
|
||||||
noVerification = cli.Flag("no-verification", "Don't verify the results.").Bool()
|
onlyVerified = cli.Flag("only-verified", "Only output verified results.").Bool()
|
||||||
onlyVerified = cli.Flag("only-verified", "Only output verified results.").Bool()
|
filterUnverified = cli.Flag("filter-unverified", "Only output first unverified result per chunk per detector if there are more than one results.").Bool()
|
||||||
filterUnverified = cli.Flag("filter-unverified", "Only output first unverified result per chunk per detector if there are more than one results.").Bool()
|
configFilename = cli.Flag("config", "Path to configuration file.").ExistingFile()
|
||||||
configFilename = cli.Flag("config", "Path to configuration file.").ExistingFile()
|
|
||||||
// rules = cli.Flag("rules", "Path to file with custom rules.").String()
|
// rules = cli.Flag("rules", "Path to file with custom rules.").String()
|
||||||
printAvgDetectorTime = cli.Flag("print-avg-detector-time", "Print the average time spent on each detector.").Bool()
|
printAvgDetectorTime = cli.Flag("print-avg-detector-time", "Print the average time spent on each detector.").Bool()
|
||||||
noUpdate = cli.Flag("no-update", "Don't check for updates.").Bool()
|
noUpdate = cli.Flag("no-update", "Don't check for updates.").Bool()
|
||||||
@@ -61,7 +60,6 @@ var (
|
|||||||
gitScanURI = gitScan.Arg("uri", "Git repository URL. https://, file://, or ssh:// schema expected.").Required().String()
|
gitScanURI = gitScan.Arg("uri", "Git repository URL. https://, file://, or ssh:// schema expected.").Required().String()
|
||||||
gitScanIncludePaths = gitScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
gitScanIncludePaths = gitScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||||
gitScanExcludePaths = gitScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
gitScanExcludePaths = gitScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||||
gitScanExcludeGlobs = gitScan.Flag("exclude-globs", "Comma separated list of globs to exclude in scan. This option filters at the `git log` level, resulting in faster scans.").String()
|
|
||||||
gitScanSinceCommit = gitScan.Flag("since-commit", "Commit to start scan from.").String()
|
gitScanSinceCommit = gitScan.Flag("since-commit", "Commit to start scan from.").String()
|
||||||
gitScanBranch = gitScan.Flag("branch", "Branch to scan.").String()
|
gitScanBranch = gitScan.Flag("branch", "Branch to scan.").String()
|
||||||
gitScanMaxDepth = gitScan.Flag("max-depth", "Maximum depth of commits to scan.").Int()
|
gitScanMaxDepth = gitScan.Flag("max-depth", "Maximum depth of commits to scan.").Int()
|
||||||
@@ -104,18 +102,6 @@ var (
|
|||||||
s3ScanCloudEnv = s3Scan.Flag("cloud-environment", "Use IAM credentials in cloud environment.").Bool()
|
s3ScanCloudEnv = s3Scan.Flag("cloud-environment", "Use IAM credentials in cloud environment.").Bool()
|
||||||
s3ScanBuckets = s3Scan.Flag("bucket", "Name of S3 bucket to scan. You can repeat this flag.").Strings()
|
s3ScanBuckets = s3Scan.Flag("bucket", "Name of S3 bucket to scan. You can repeat this flag.").Strings()
|
||||||
|
|
||||||
gcsScan = cli.Command("gcs", "Find credentials in GCS buckets.")
|
|
||||||
gcsProjectID = gcsScan.Flag("project-id", "GCS project ID used to authenticate. Can NOT be used with unauth scan. Can be provided with environment variable GOOGLE_CLOUD_PROJECT.").Envar("GOOGLE_CLOUD_PROJECT").String()
|
|
||||||
gcsCloudEnv = gcsScan.Flag("cloud-environment", "Use Application Default Credentials, IAM credentials to authenticate.").Bool()
|
|
||||||
gcsServiceAccount = gcsScan.Flag("service-account", "Path to GCS service account JSON file.").ExistingFile()
|
|
||||||
gcsWithoutAuth = gcsScan.Flag("without-auth", "Scan GCS buckets without authentication. This will only work for public buckets").Bool()
|
|
||||||
gcsAPIKey = gcsScan.Flag("api-key", "GCS API key used to authenticate. Can be provided with environment variable GOOGLE_API_KEY.").Envar("GOOGLE_API_KEY").String()
|
|
||||||
gcsIncludeBuckets = gcsScan.Flag("include-buckets", "Buckets to scan. Comma seperated list of buckets. You can repeat this flag. Globs are supported").Short('I').Strings()
|
|
||||||
gcsExcludeBuckets = gcsScan.Flag("exclude-buckets", "Buckets to exclude from scan. Comma separated list of buckets. Globs are supported").Short('X').Strings()
|
|
||||||
gcsIncludeObjects = gcsScan.Flag("include-objects", "Objects to scan. Comma separated list of objects. you can repeat this flag. Globs are supported").Short('i').Strings()
|
|
||||||
gcsExcludeObjects = gcsScan.Flag("exclude-objects", "Objects to exclude from scan. Comma separated list of objects. You can repeat this flag. Globs are supported").Short('x').Strings()
|
|
||||||
gcsMaxObjectSize = gcsScan.Flag("max-object-size", "Maximum size of objects to scan. Objects larger than this will be skipped. (Byte units eg. 512B, 2KB, 4MB)").Default("10MB").Bytes()
|
|
||||||
|
|
||||||
syslogScan = cli.Command("syslog", "Scan syslog")
|
syslogScan = cli.Command("syslog", "Scan syslog")
|
||||||
syslogAddress = syslogScan.Flag("address", "Address and port to listen on for syslog. Example: 127.0.0.1:514").String()
|
syslogAddress = syslogScan.Flag("address", "Address and port to listen on for syslog. Example: 127.0.0.1:514").String()
|
||||||
syslogProtocol = syslogScan.Flag("protocol", "Protocol to listen on. udp or tcp").String()
|
syslogProtocol = syslogScan.Flag("protocol", "Protocol to listen on. udp or tcp").String()
|
||||||
@@ -303,18 +289,13 @@ func run(state overseer.State) {
|
|||||||
if remote {
|
if remote {
|
||||||
defer os.RemoveAll(repoPath)
|
defer os.RemoveAll(repoPath)
|
||||||
}
|
}
|
||||||
excludedGlobs := []string{}
|
|
||||||
if *gitScanExcludeGlobs != "" {
|
|
||||||
excludedGlobs = strings.Split(*gitScanExcludeGlobs, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := sources.GitConfig{
|
cfg := sources.GitConfig{
|
||||||
RepoPath: repoPath,
|
RepoPath: repoPath,
|
||||||
HeadRef: *gitScanBranch,
|
HeadRef: *gitScanBranch,
|
||||||
BaseRef: *gitScanSinceCommit,
|
BaseRef: *gitScanSinceCommit,
|
||||||
MaxDepth: *gitScanMaxDepth,
|
MaxDepth: *gitScanMaxDepth,
|
||||||
Filter: filter,
|
Filter: filter,
|
||||||
ExcludeGlobs: excludedGlobs,
|
|
||||||
}
|
}
|
||||||
if err = e.ScanGit(ctx, cfg); err != nil {
|
if err = e.ScanGit(ctx, cfg); err != nil {
|
||||||
logFatal(err, "Failed to scan Git.")
|
logFatal(err, "Failed to scan Git.")
|
||||||
@@ -402,23 +383,6 @@ func run(state overseer.State) {
|
|||||||
if err := e.ScanCircleCI(ctx, *circleCiScanToken); err != nil {
|
if err := e.ScanCircleCI(ctx, *circleCiScanToken); err != nil {
|
||||||
logFatal(err, "Failed to scan CircleCI.")
|
logFatal(err, "Failed to scan CircleCI.")
|
||||||
}
|
}
|
||||||
case gcsScan.FullCommand():
|
|
||||||
cfg := sources.GCSConfig{
|
|
||||||
ProjectID: *gcsProjectID,
|
|
||||||
CloudCred: *gcsCloudEnv,
|
|
||||||
ServiceAccount: *gcsServiceAccount,
|
|
||||||
WithoutAuth: *gcsWithoutAuth,
|
|
||||||
ApiKey: *gcsAPIKey,
|
|
||||||
IncludeBuckets: commaSeperatedToSlice(*gcsIncludeBuckets),
|
|
||||||
ExcludeBuckets: commaSeperatedToSlice(*gcsExcludeBuckets),
|
|
||||||
IncludeObjects: commaSeperatedToSlice(*gcsIncludeObjects),
|
|
||||||
ExcludeObjects: commaSeperatedToSlice(*gcsExcludeObjects),
|
|
||||||
Concurrency: *concurrency,
|
|
||||||
MaxObjectSize: int64(*gcsMaxObjectSize),
|
|
||||||
}
|
|
||||||
if err := e.ScanGCS(ctx, cfg); err != nil {
|
|
||||||
logFatal(err, "Failed to scan GCS.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// asynchronously wait for scanning to finish and cleanup
|
// asynchronously wait for scanning to finish and cleanup
|
||||||
go e.Finish(ctx)
|
go e.Finish(ctx)
|
||||||
@@ -442,8 +406,6 @@ func run(state overseer.State) {
|
|||||||
err = output.PrintLegacyJSON(ctx, &r)
|
err = output.PrintLegacyJSON(ctx, &r)
|
||||||
case *jsonOut:
|
case *jsonOut:
|
||||||
err = output.PrintJSON(&r)
|
err = output.PrintJSON(&r)
|
||||||
case *gitHubActionsFormat:
|
|
||||||
err = output.PrintGitHubActionsOutput(&r)
|
|
||||||
default:
|
default:
|
||||||
err = output.PrintPlainOutput(&r)
|
err = output.PrintPlainOutput(&r)
|
||||||
}
|
}
|
||||||
@@ -466,20 +428,6 @@ func run(state overseer.State) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func commaSeperatedToSlice(s []string) []string {
|
|
||||||
var result []string
|
|
||||||
for _, items := range s {
|
|
||||||
for _, item := range strings.Split(items, ",") {
|
|
||||||
item = strings.TrimSpace(item)
|
|
||||||
if item == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result = append(result, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func printAverageDetectorTime(e *engine.Engine) {
|
func printAverageDetectorTime(e *engine.Engine) {
|
||||||
fmt.Fprintln(os.Stderr, "Average detector time is the measurement of average time spent on each detector when results are returned.")
|
fmt.Fprintln(os.Stderr, "Average detector time is the measurement of average time spent on each detector when results are returned.")
|
||||||
for detectorName, durations := range e.DetectorAvgTime() {
|
for detectorName, durations := range e.DetectorAvgTime() {
|
||||||
|
|||||||
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
// Package cache provides an interface which can be implemented by different cache types.
|
|
||||||
package cache
|
|
||||||
|
|
||||||
// Cache is used to store key/value pairs.
|
|
||||||
type Cache interface {
|
|
||||||
// Set stores the given key/value pair.
|
|
||||||
Set(string, string)
|
|
||||||
// Get returns the value for the given key and a boolean indicating if the key was found.
|
|
||||||
Get(string) (string, bool)
|
|
||||||
// Exists returns true if the given key exists in the cache.
|
|
||||||
Exists(string) bool
|
|
||||||
// Delete the given key from the cache.
|
|
||||||
Delete(string)
|
|
||||||
// Clear all key/value pairs from the cache.
|
|
||||||
Clear()
|
|
||||||
// Count the number of key/value pairs in the cache.
|
|
||||||
Count() int
|
|
||||||
// Contents returns all keys in the cache encoded as a string.
|
|
||||||
Contents() string
|
|
||||||
}
|
|
||||||
Vendored
-85
@@ -1,85 +0,0 @@
|
|||||||
package memory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
expirationInterval = 12 * time.Hour
|
|
||||||
purgeInterval = 13 * time.Hour
|
|
||||||
defaultExpiration = cache.DefaultExpiration
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cache is a wrapper around the go-cache library.
|
|
||||||
type Cache struct {
|
|
||||||
c *cache.Cache
|
|
||||||
}
|
|
||||||
|
|
||||||
// New constructs a new in-memory cache.
|
|
||||||
func New() *Cache {
|
|
||||||
c := cache.New(expirationInterval, purgeInterval)
|
|
||||||
return &Cache{c: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWithData constructs a new in-memory cache with existing data.
|
|
||||||
func NewWithData(ctx context.Context, data []string) *Cache {
|
|
||||||
ctx.Logger().V(3).Info("Loading cache", "num-items", len(data))
|
|
||||||
|
|
||||||
items := make(map[string]cache.Item, len(data))
|
|
||||||
for _, d := range data {
|
|
||||||
items[d] = cache.Item{Object: d, Expiration: int64(defaultExpiration)}
|
|
||||||
}
|
|
||||||
|
|
||||||
c := cache.NewFrom(expirationInterval, purgeInterval, items)
|
|
||||||
return &Cache{c: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set adds a key-value pair to the cache.
|
|
||||||
func (c *Cache) Set(key, value string) {
|
|
||||||
c.c.Set(key, value, defaultExpiration)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the value for the given key.
|
|
||||||
func (c *Cache) Get(key string) (string, bool) {
|
|
||||||
res, ok := c.c.Get(key)
|
|
||||||
if !ok {
|
|
||||||
return "", ok
|
|
||||||
}
|
|
||||||
return res.(string), ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exists returns true if the given key exists in the cache.
|
|
||||||
func (c *Cache) Exists(key string) bool {
|
|
||||||
_, ok := c.c.Get(key)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete removes the key-value pair from the cache.
|
|
||||||
func (c *Cache) Delete(key string) {
|
|
||||||
c.c.Delete(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear removes all key-value pairs from the cache.
|
|
||||||
func (c *Cache) Clear() {
|
|
||||||
c.c.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the number of key-value pairs in the cache.
|
|
||||||
func (c *Cache) Count() int {
|
|
||||||
return c.c.ItemCount()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contents returns all key-value pairs in the cache encodes as a string.
|
|
||||||
func (c *Cache) Contents() string {
|
|
||||||
items := c.c.Items()
|
|
||||||
res := make([]string, 0, len(items))
|
|
||||||
for k := range items {
|
|
||||||
res = append(res, k)
|
|
||||||
}
|
|
||||||
return strings.Join(res, ",")
|
|
||||||
}
|
|
||||||
Vendored
-153
@@ -1,153 +0,0 @@
|
|||||||
package memory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
|
|
||||||
logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCache(t *testing.T) {
|
|
||||||
c := New()
|
|
||||||
|
|
||||||
// Test set and get.
|
|
||||||
c.Set("key1", "key1")
|
|
||||||
v, ok := c.Get("key1")
|
|
||||||
if !ok || v != "key1" {
|
|
||||||
t.Fatalf("Unexpected value for key1: %v, %v", v, ok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test exists.
|
|
||||||
if !c.Exists("key1") {
|
|
||||||
t.Fatalf("Expected key1 to exist")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the count.
|
|
||||||
if c.Count() != 1 {
|
|
||||||
t.Fatalf("Unexpected count: %d", c.Count())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test delete.
|
|
||||||
c.Delete("key1")
|
|
||||||
v, ok = c.Get("key1")
|
|
||||||
if ok || v != "" {
|
|
||||||
t.Fatalf("Unexpected value for key1 after delete: %v, %v", v, ok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test clear.
|
|
||||||
c.Set("key10", "key10")
|
|
||||||
c.Clear()
|
|
||||||
v, ok = c.Get("key10")
|
|
||||||
if ok || v != "" {
|
|
||||||
t.Fatalf("Unexpected value for key10 after clear: %v, %v", v, ok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test contents.
|
|
||||||
keys := []string{"key1", "key2", "key3"}
|
|
||||||
for _, k := range keys {
|
|
||||||
c.Set(k, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
items := c.Contents()
|
|
||||||
sort.Strings(keys)
|
|
||||||
res := strings.Split(items, ",")
|
|
||||||
sort.Strings(res)
|
|
||||||
|
|
||||||
if len(keys) != len(res) {
|
|
||||||
t.Fatalf("Unexpected length of items: %d", len(res))
|
|
||||||
}
|
|
||||||
if !cmp.Equal(keys, res) {
|
|
||||||
t.Fatalf("Unexpected items: %v", res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCache_NewWithData(t *testing.T) {
|
|
||||||
c := NewWithData(logContext.Background(), []string{"key1", "key2", "key3"})
|
|
||||||
|
|
||||||
// Test the count.
|
|
||||||
if c.Count() != 3 {
|
|
||||||
t.Fatalf("Unexpected count: %d", c.Count())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test contents.
|
|
||||||
keys := []string{"key1", "key2", "key3"}
|
|
||||||
items := c.Contents()
|
|
||||||
sort.Strings(keys)
|
|
||||||
res := strings.Split(items, ",")
|
|
||||||
sort.Strings(res)
|
|
||||||
|
|
||||||
if len(keys) != len(res) {
|
|
||||||
t.Fatalf("Unexpected length of items: %d", len(res))
|
|
||||||
}
|
|
||||||
if !cmp.Equal(keys, res) {
|
|
||||||
t.Fatalf("Unexpected items: %v", res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupBenchmarks(b *testing.B) *Cache {
|
|
||||||
b.Helper()
|
|
||||||
|
|
||||||
c := New()
|
|
||||||
|
|
||||||
for i := 0; i < 500_000; i++ {
|
|
||||||
key := fmt.Sprintf("key%d", i)
|
|
||||||
c.Set(key, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSet(b *testing.B) {
|
|
||||||
c := New()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
key := fmt.Sprintf("key%d", i)
|
|
||||||
c.Set(key, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGet(b *testing.B) {
|
|
||||||
c := setupBenchmarks(b)
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
key := fmt.Sprintf("key%d", i)
|
|
||||||
c.Get(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkDelete(b *testing.B) {
|
|
||||||
c := setupBenchmarks(b)
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
key := fmt.Sprintf("key%d", i)
|
|
||||||
c.Delete(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCount(b *testing.B) {
|
|
||||||
c := setupBenchmarks(b)
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
c.Count()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkContents(b *testing.B) {
|
|
||||||
c := setupBenchmarks(b)
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
var s string
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
s = c.Contents()
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = s
|
|
||||||
}
|
|
||||||
+3
-4
@@ -2,17 +2,16 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
KB, MB, GB, TB, PB = 1e3, 1e6, 1e9, 1e12, 1e15
|
KB, MB, GB, TB, PB = 1e3, 1e6, 1e9, 1e12, 1e15
|
||||||
IgnoredExtensions = []string{"mp4", "avi", "mpeg", "mpg", "mov", "wmv", "m4p", "swf", "mp2", "flv", "vob", "webm", "hdv", "3gp", "ogg", "mp3", "wav", "flac", "webp"}
|
IGNORED_EXTENSIONS = []string{"mp4", "avi", "mpeg", "mpg", "mov", "wmv", "m4p", "swf", "mp2", "flv", "vob", "webm", "hdv", "3gp", "ogg", "mp3", "wav", "flac", "webp"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func SkipFile(filename string) bool {
|
func SkipFile(filename string) bool {
|
||||||
for _, ext := range IgnoredExtensions {
|
for _, ext := range IGNORED_EXTENSIONS {
|
||||||
if strings.TrimPrefix(filepath.Ext(filename), ".") == ext {
|
if filepath.Ext(filename) == ext {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
package common
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestSkipFile(t *testing.T) {
|
|
||||||
type testCase struct {
|
|
||||||
file string
|
|
||||||
want bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a test case for each ignored extension.
|
|
||||||
testCases := make([]testCase, 0, len(IgnoredExtensions)+1)
|
|
||||||
for _, ext := range IgnoredExtensions {
|
|
||||||
testCases = append(testCases, testCase{
|
|
||||||
file: "test." + ext,
|
|
||||||
want: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a test case for a file that should not be skipped.
|
|
||||||
testCases = append(testCases, testCase{file: "test.txt", want: false})
|
|
||||||
|
|
||||||
for _, tt := range testCases {
|
|
||||||
t.Run(tt.file, func(t *testing.T) {
|
|
||||||
if got := SkipFile(tt.file); got != tt.want {
|
|
||||||
t.Errorf("SkipFile(%v) got %v, want %v", tt.file, got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSkipFile(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
SkipFile("test.mp4")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -94,8 +94,9 @@ func (c *customRegexWebhook) FromData(ctx context.Context, verify bool, data []b
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore any errors and collect as many of the results as we can.
|
if err := g.Wait(); err != nil {
|
||||||
_ = g.Wait()
|
return nil, err
|
||||||
|
}
|
||||||
close(resultsCh)
|
close(resultsCh)
|
||||||
|
|
||||||
for result := range resultsCh {
|
for result := range resultsCh {
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package alchemy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"alchemy"}) + `\b([0-9a-zA-Z]{23}_[0-9a-zA-Z]{8})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"alchemy"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Alchemy secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://eth-mainnet.g.alchemy.com/v2/"+resMatch+"/getNFTs/?owner=vitalik.eth", nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode >= 200 && res.StatusCode < 300 {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_Alchemy
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package alchemy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAlchemy_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("ALCHEMY")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("ALCHEMY_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a alchemy secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a alchemy secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Alchemy.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Alchemy.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package blocknative
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"blocknative"}) + `\b([0-9Aa-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"blocknative"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Blocknative secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_BlockNative,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.blocknative.com/gasprices/blockprices", nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Add("Authorization", fmt.Sprintf("%s", resMatch))
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
bodyBytes, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
body := string(bodyBytes)
|
|
||||||
if !strings.Contains(body, "valid") {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_BlockNative
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package blocknative
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBlocknative_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("BLOCKNATIVE")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("BLOCKNATIVE_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a blocknative secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_BlockNative,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a blocknative secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_BlockNative,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Blocknative.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Blocknative.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,8 +20,8 @@ var (
|
|||||||
client = common.SaneHttpClient()
|
client = common.SaneHttpClient()
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"https://", "http://", "hub-cloud.browserstack.com", "accessKey", "\"access_Key\":", "ACCESS_KEY", "key", "browserstackKey", "BS_AUTHKEY", "BROWSERSTACK_ACCESS_KEY"}) + `\b([0-9a-zA-Z]{20})\b`)
|
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"browserstack", "key", "automate", "local"}) + `\b([0-9a-zA-Z]{20})\b`)
|
||||||
userPat = regexp.MustCompile(detectors.PrefixRegex([]string{"https://", "http://", "hub-cloud.browserstack.com", "userName", "\"username\":", "USER_NAME", "user", "browserstackUser", "BS_USERNAME", "BROWSERSTACK_USERNAME"}) + `\b([a-zA-Z\d]{3,18}[._-]+[a-zA-Z\d]{6})\b`)
|
userPat = regexp.MustCompile(detectors.PrefixRegex([]string{"browserstack", "user", "automate", "local"}) + `\b([a-zA-Z\d]{3,18}[._-]?[a-zA-Z\d]{6})\b`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
// Keywords are used for efficiently pre-filtering chunks.
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
package bscscan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"bscscan"}) + `\b([0-9A-Z]{34})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"bscscan"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Bscscan secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_BscScan,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.bscscan.com/api?module=account&action=balance&address=0x70F657164e5b75689b64B7fd1fA275F334f28e18&apikey="+resMatch, nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
bodyBytes, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
body := string(bodyBytes)
|
|
||||||
|
|
||||||
if !strings.Contains(body, "NOTOK") {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sur>
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_BscScan
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package bscscan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBscscan_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("BSCSCAN")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("BSCSCAN_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a bscscan secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_BscScan,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a bscscan secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_BscScan,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Bscscan.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Bscscan.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
package coinmarketcap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"coinmarketcap","CMC"}) + `\b([0-9Aa-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"coinmarketcap","CMC"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Coinmarketcap secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_CoinMarketCap,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?start=1&limit=5000&convert=USD", nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
req.Header.Add("X-CMC_PRO_API_KEY", fmt.Sprintf("%s", resMatch))
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode >= 200 && res.StatusCode < 300 {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_CoinMarketCap
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package coinmarketcap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCoinmarketcap_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("COINMARKETCAP")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("COINMARKETCAP_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a coinmarketcap secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_CoinMarketCap,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a coinmarketcap secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_CoinMarketCap,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Coinmarketcap.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Coinmarketcap.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package etherscan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"etherscan"}) + `\b([0-9A-Z]{34})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"etherscan"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Etherscan secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_Etherscan,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.etherscan.io/api?module=account&action=balance&address=0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae&tag=latest&apikey="+resMatch, nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
bodyBytes, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
body := string(bodyBytes)
|
|
||||||
|
|
||||||
if strings.Contains(body, `"OK"`) {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_Etherscan
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package etherscan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEtherscan_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("ETHERSCAN")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("ETHERSCAN_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a etherscan secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Etherscan,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a etherscan secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Etherscan,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Etherscan.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Etherscan.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package infura
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"infura"}) + `\b([0-9a-z]{32})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"infura"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Infura secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_Infura,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
payload := strings.NewReader(`{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}`)
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", "https://mainnet.infura.io/v3/"+resMatch, payload)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Add("Content-Type", "application/json")
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
bodyBytes, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
body := string(bodyBytes)
|
|
||||||
if strings.Contains(body, `"result"`) {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_Infura
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package infura
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestInfura_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("INFURA")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("INFURA_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a infura secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Infura,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a infura secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Infura,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Infura.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Infura.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Scanner struct{}
|
type Scanner struct{}
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
// Ensure the Scanner satisfies the interface at compile time.
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
var _ detectors.Detector = (*Scanner)(nil)
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
|||||||
}
|
}
|
||||||
body := string(bodyBytes)
|
body := string(bodyBytes)
|
||||||
|
|
||||||
if !strings.Contains(body, "AUTHFAIL") {
|
if !strings.Contains(body, "INVALIDTOKEN") {
|
||||||
s1.Verified = true
|
s1.Verified = true
|
||||||
} else {
|
} else {
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
package moralis
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
client = common.SaneHttpClient()
|
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
||||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"moralis"}) + `\b([0-9a-zA-Z]{64})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"moralis"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify Moralis secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resMatch := strings.TrimSpace(match[1])
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_Moralis,
|
|
||||||
Raw: []byte(resMatch),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://deep-index.moralis.io/api/v2/0xd8da6bf26964af9d7eed9e03e53415d37aa96045/nft?chain=eth&format=decimal", nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
req.Header.Add("X-API-Key", fmt.Sprintf("%s", resMatch))
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode >= 200 && res.StatusCode < 300 {
|
|
||||||
s1.Verified = true
|
|
||||||
} else {
|
|
||||||
// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
|
|
||||||
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_Moralis
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package moralis
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMoralis_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
secret := testSecrets.MustGetField("MORALIS")
|
|
||||||
inactiveSecret := testSecrets.MustGetField("MORALIS_INACTIVE")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "found, verified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a moralis secret %s within", secret)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Moralis,
|
|
||||||
Verified: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "found, unverified",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find a moralis secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_Moralis,
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Moralis.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("Moralis.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
package openai
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Scanner struct{}
|
|
||||||
|
|
||||||
// Ensure the Scanner satisfies the interface at compile time.
|
|
||||||
var _ detectors.Detector = (*Scanner)(nil)
|
|
||||||
|
|
||||||
var (
|
|
||||||
keyPat = regexp.MustCompile(`\b((?:sk)-[a-zA-Z0-9]{48})\b`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Add secret context?? Information about access, ownership etc
|
|
||||||
type orgResponse struct {
|
|
||||||
Data []organization `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type organization struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
User string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Personal bool `json:"personal"`
|
|
||||||
Default bool `json:"is_default"`
|
|
||||||
Role string `json:"role"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
|
||||||
// Use identifiers in the secret preferably, or the provider name.
|
|
||||||
func (s Scanner) Keywords() []string {
|
|
||||||
return []string{"sk-"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromData will find and optionally verify OpenAI secrets in a given set of bytes.
|
|
||||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
||||||
dataStr := string(data)
|
|
||||||
|
|
||||||
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
||||||
|
|
||||||
for _, match := range matches {
|
|
||||||
// First match is entire regex, second is the first group.
|
|
||||||
if len(match) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
token := match[1]
|
|
||||||
|
|
||||||
s1 := detectors.Result{
|
|
||||||
DetectorType: detectorspb.DetectorType_OpenAI,
|
|
||||||
Redacted: token[:3] + "..." + token[47:],
|
|
||||||
Raw: []byte(token),
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify {
|
|
||||||
client := common.SaneHttpClient()
|
|
||||||
// Undocumented API
|
|
||||||
// https://api.openai.com/v1/organizations
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.openai.com/v1/organizations", nil)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Add("Content-Type", "application/json; charset=utf-8")
|
|
||||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err == nil {
|
|
||||||
if res.StatusCode >= 200 && res.StatusCode < 300 {
|
|
||||||
var orgs orgResponse
|
|
||||||
err = json.NewDecoder(res.Body).Decode(&orgs)
|
|
||||||
res.Body.Close()
|
|
||||||
if err == nil {
|
|
||||||
s1.Verified = true
|
|
||||||
org := orgs.Data[0]
|
|
||||||
s1.ExtraData = map[string]string{
|
|
||||||
"id": org.Id,
|
|
||||||
"title": org.Title,
|
|
||||||
"user": org.User,
|
|
||||||
"description": org.Description,
|
|
||||||
"role": org.Role,
|
|
||||||
"is_personal": strconv.FormatBool(org.Personal),
|
|
||||||
"is_default": strconv.FormatBool(org.Default),
|
|
||||||
"total_orgs": fmt.Sprintf("%d", len(orgs.Data)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s1.Verified && detectors.IsKnownFalsePositive(string(s1.Raw), detectors.DefaultFalsePositives, true) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
results = append(results, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) Type() detectorspb.DetectorType {
|
|
||||||
return detectorspb.DetectorType_OpenAI
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
//go:build detectors
|
|
||||||
// +build detectors
|
|
||||||
|
|
||||||
package openai
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOpenAI_FromChunk(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
defer cancel()
|
|
||||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
oaiUnverified := testSecrets.MustGetField("OPENAI_UNVERIFIED")
|
|
||||||
oaiVerified := testSecrets.MustGetField("OPENAI_VERIFIED")
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
data []byte
|
|
||||||
verify bool
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
s Scanner
|
|
||||||
args args
|
|
||||||
want []detectors.Result
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Found, unverified OpenAI token sk-",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find an OpenAI secret %s within", oaiUnverified)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_OpenAI,
|
|
||||||
Redacted: "sk-...gOPc",
|
|
||||||
Verified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Found, verified OpenAI token sk-",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte(fmt.Sprintf("You can find an OpenAI secret %s within", oaiVerified)),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: []detectors.Result{
|
|
||||||
{
|
|
||||||
DetectorType: detectorspb.DetectorType_OpenAI,
|
|
||||||
Verified: true,
|
|
||||||
Redacted: "sk-...gOPb",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not found",
|
|
||||||
s: Scanner{},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
data: []byte("You cannot find the secret within"),
|
|
||||||
verify: true,
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
s := Scanner{}
|
|
||||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("OpenAI.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
if len(got[i].Raw) == 0 {
|
|
||||||
t.Fatal("no raw secret present")
|
|
||||||
}
|
|
||||||
got[i].Raw = nil
|
|
||||||
got[i].ExtraData = nil
|
|
||||||
}
|
|
||||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
|
||||||
t.Errorf("OpenAI.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFromData(benchmark *testing.B) {
|
|
||||||
ctx := context.Background()
|
|
||||||
s := Scanner{}
|
|
||||||
for name, data := range detectors.MustGetBenchmarkData() {
|
|
||||||
benchmark.Run(name, func(b *testing.B) {
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
_, err := s.FromData(ctx, false, data)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,7 @@ var (
|
|||||||
client = common.SaneHttpClient()
|
client = common.SaneHttpClient()
|
||||||
|
|
||||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
||||||
keyPat = regexp.MustCompile(`(https://hooks\.slack\.com/services/T[A-Z0-9]+/B[A-Z0-9]+/[A-Za-z0-9]{23,25})`)
|
keyPat = regexp.MustCompile(`(https://hooks\.slack\.com/services/[A-Za-z0-9+/]{44,46})`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Keywords are used for efficiently pre-filtering chunks.
|
// Keywords are used for efficiently pre-filtering chunks.
|
||||||
@@ -62,7 +62,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
body := string(bodyBytes)
|
body := string(bodyBytes)
|
||||||
if (res.StatusCode >= 200 && res.StatusCode < 300) || (res.StatusCode == 400 && strings.Contains(body, "no_text")) {
|
if (res.StatusCode >= 200 && res.StatusCode < 300) || (res.StatusCode == 400 && strings.Contains(body, "text")) {
|
||||||
s1.Verified = true
|
s1.Verified = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,7 +442,6 @@ import (
|
|||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/onesignal"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/onesignal"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/onwaterio"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/onwaterio"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/oopspam"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/oopspam"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/openai"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/opencagedata"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/opencagedata"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/opengraphr"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/opengraphr"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/openuv"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/openuv"
|
||||||
@@ -731,13 +730,6 @@ import (
|
|||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zipcodebase"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zipcodebase"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zonkafeedback"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zonkafeedback"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zulipchat"
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/zulipchat"
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/etherscan"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/infura"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/alchemy"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/blocknative"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/moralis"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/bscscan"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/coinmarketcap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func DefaultDetectors() []detectors.Detector {
|
func DefaultDetectors() []detectors.Detector {
|
||||||
@@ -1174,7 +1166,6 @@ func DefaultDetectors() []detectors.Detector {
|
|||||||
signupgenius.Scanner{},
|
signupgenius.Scanner{},
|
||||||
streak.Scanner{},
|
streak.Scanner{},
|
||||||
route4me.Scanner{},
|
route4me.Scanner{},
|
||||||
openai.Scanner{},
|
|
||||||
opencagedata.Scanner{},
|
opencagedata.Scanner{},
|
||||||
positionstack.Scanner{},
|
positionstack.Scanner{},
|
||||||
upcdatabase.Scanner{},
|
upcdatabase.Scanner{},
|
||||||
@@ -1497,12 +1488,5 @@ func DefaultDetectors() []detectors.Detector {
|
|||||||
ftp.Scanner{},
|
ftp.Scanner{},
|
||||||
ldap.Scanner{},
|
ldap.Scanner{},
|
||||||
shopify.Scanner{},
|
shopify.Scanner{},
|
||||||
etherscan.Scanner{},
|
|
||||||
infura.Scanner{},
|
|
||||||
alchemy.Scanner{},
|
|
||||||
blocknative.Scanner{},
|
|
||||||
moralis.Scanner{},
|
|
||||||
bscscan.Scanner{},
|
|
||||||
coinmarketcap.Scanner{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,7 +260,6 @@ func (e *Engine) detectorWorker(ctx context.Context) {
|
|||||||
for _, kw := range detector.Keywords() {
|
for _, kw := range detector.Keywords() {
|
||||||
if _, ok := matchedKeywords[strings.ToLower(kw)]; ok {
|
if _, ok := matchedKeywords[strings.ToLower(kw)]; ok {
|
||||||
chunkContainsKeyword = true
|
chunkContainsKeyword = true
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"google.golang.org/protobuf/types/known/anypb"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources/gcs"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ScanGCS with the provided options.
|
|
||||||
func (e *Engine) ScanGCS(ctx context.Context, c sources.GCSConfig) error {
|
|
||||||
// Project ID is required if using any authenticated access.
|
|
||||||
if c.ProjectID == "" && !c.WithoutAuth {
|
|
||||||
return fmt.Errorf("project ID is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If using unauthenticated access, the project ID is not used.
|
|
||||||
if c.ProjectID != "" && c.WithoutAuth {
|
|
||||||
c.ProjectID = ""
|
|
||||||
ctx.Logger().Info("project ID is not used when using unauthenticated access, ignoring provided project ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
connection := &sourcespb.GCS{
|
|
||||||
ProjectId: c.ProjectID,
|
|
||||||
IncludeBuckets: c.IncludeBuckets,
|
|
||||||
ExcludeBuckets: c.ExcludeBuckets,
|
|
||||||
IncludeObjects: c.IncludeObjects,
|
|
||||||
ExcludeObjects: c.ExcludeObjects,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure only one auth method is selected.
|
|
||||||
if !isAuthValid(ctx, c, connection) {
|
|
||||||
return fmt.Errorf("multiple auth methods selected, please select only one")
|
|
||||||
}
|
|
||||||
|
|
||||||
var conn anypb.Any
|
|
||||||
err := anypb.MarshalFrom(&conn, connection, proto.MarshalOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to marshal GCS connection: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
source := gcs.Source{}
|
|
||||||
ctx = context.WithValues(ctx,
|
|
||||||
"source_type", source.Type().String(),
|
|
||||||
"source_name", "gcs",
|
|
||||||
)
|
|
||||||
if err = source.Init(ctx, "trufflehog - GCS", 0, 0, true, &conn, int(c.Concurrency)); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize GCS source: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.sourcesWg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer common.RecoverWithExit(ctx)
|
|
||||||
defer e.sourcesWg.Done()
|
|
||||||
if err := source.Chunks(ctx, e.ChunksChan()); err != nil {
|
|
||||||
ctx.Logger().Error(err, "could not scan GCS")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isAuthValid(ctx context.Context, c sources.GCSConfig, connection *sourcespb.GCS) bool {
|
|
||||||
var isAuthSelected bool
|
|
||||||
|
|
||||||
if c.WithoutAuth {
|
|
||||||
isAuthSelected = true
|
|
||||||
connection.Credential = &sourcespb.GCS_Unauthenticated{}
|
|
||||||
}
|
|
||||||
if c.CloudCred {
|
|
||||||
if isAuthSelected {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
isAuthSelected = true
|
|
||||||
connection.Credential = &sourcespb.GCS_Adc{}
|
|
||||||
}
|
|
||||||
if c.ServiceAccount != "" {
|
|
||||||
if isAuthSelected {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
isAuthSelected = true
|
|
||||||
connection.Credential = &sourcespb.GCS_ServiceAccountFile{
|
|
||||||
ServiceAccountFile: c.ServiceAccount,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.ApiKey != "" {
|
|
||||||
if isAuthSelected {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
isAuthSelected = true
|
|
||||||
connection.Credential = &sourcespb.GCS_ApiKey{
|
|
||||||
ApiKey: c.ApiKey,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !isAuthSelected {
|
|
||||||
ctx.Logger().Info("no auth method selected, using unauthenticated")
|
|
||||||
connection.Credential = &sourcespb.GCS_Unauthenticated{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestScanGCS(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
gcsConfig sources.GCSConfig
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "scanned GCS",
|
|
||||||
gcsConfig: sources.GCSConfig{
|
|
||||||
ApiKey: "abc123",
|
|
||||||
ProjectID: "test-project",
|
|
||||||
CloudCred: false,
|
|
||||||
WithoutAuth: false,
|
|
||||||
ServiceAccount: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "missing project ID, with auth",
|
|
||||||
gcsConfig: sources.GCSConfig{ApiKey: "abc123"},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "missing project ID, without auth, public scan",
|
|
||||||
gcsConfig: sources.GCSConfig{WithoutAuth: true},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multiple selected auth methods",
|
|
||||||
gcsConfig: sources.GCSConfig{
|
|
||||||
ApiKey: "abc123",
|
|
||||||
ProjectID: "test-project",
|
|
||||||
CloudCred: true,
|
|
||||||
WithoutAuth: false,
|
|
||||||
ServiceAccount: "",
|
|
||||||
},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no auth method selected",
|
|
||||||
gcsConfig: sources.GCSConfig{
|
|
||||||
ProjectID: "test-project",
|
|
||||||
MaxObjectSize: 10 * 1024 * 1024,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
e := &Engine{}
|
|
||||||
err := e.ScanGCS(context.Background(), test.gcsConfig)
|
|
||||||
if err != nil && !test.wantErr && !strings.Contains(err.Error(), "googleapi: Error 400: Bad Request") {
|
|
||||||
t.Errorf("ScanGCS() got: %v, want: %v", err, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil && test.wantErr {
|
|
||||||
t.Errorf("ScanGCS() got: %v, want: %v", err, "error")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -36,9 +36,6 @@ func (e *Engine) ScanGit(ctx context.Context, c sources.GitConfig) error {
|
|||||||
if c.HeadRef != "" {
|
if c.HeadRef != "" {
|
||||||
opts = append(opts, git.ScanOptionHeadCommit(c.HeadRef))
|
opts = append(opts, git.ScanOptionHeadCommit(c.HeadRef))
|
||||||
}
|
}
|
||||||
if c.ExcludeGlobs != nil {
|
|
||||||
opts = append(opts, git.ScanOptionExcludeGlobs(c.ExcludeGlobs))
|
|
||||||
}
|
|
||||||
scanOptions := git.NewScanOptions(opts...)
|
scanOptions := git.NewScanOptions(opts...)
|
||||||
|
|
||||||
gitSource := git.NewGit(sourcespb.SourceType_SOURCE_TYPE_GIT, 0, 0, "trufflehog - git", true, runtime.NumCPU(),
|
gitSource := git.NewGit(sourcespb.SourceType_SOURCE_TYPE_GIT, 0, 0, "trufflehog - git", true, runtime.NumCPU(),
|
||||||
|
|||||||
+146
-13
@@ -116,27 +116,22 @@ func (c1 *Commit) Equal(c2 *Commit) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RepoPath parses the output of the `git log` command for the `source` path.
|
// RepoPath parses the output of the `git log` command for the `source` path.
|
||||||
func (c *Parser) RepoPath(ctx context.Context, source string, head string, abbreviatedLog bool, excludedGlobs []string) (chan Commit, error) {
|
func (c *Parser) RepoPath(ctx context.Context, source string, head string, abbreviatedLog bool) (chan Commit, error) {
|
||||||
args := []string{"-C", source, "log", "-p", "-U5", "--full-history", "--date=format:%a %b %d %H:%M:%S %Y %z"}
|
args := []string{"-C", source, "log", "--full-history", "--date=format:%a %b %d %H:%M:%S %Y %z"}
|
||||||
if abbreviatedLog {
|
|
||||||
args = append(args, "--diff-filter=AM")
|
|
||||||
}
|
|
||||||
if head != "" {
|
if head != "" {
|
||||||
args = append(args, head)
|
args = append(args, head)
|
||||||
} else {
|
} else {
|
||||||
args = append(args, "--all")
|
args = append(args, "--all")
|
||||||
}
|
}
|
||||||
for _, glob := range excludedGlobs {
|
|
||||||
args = append(args, "--", ".", fmt.Sprintf(":(exclude)%s", glob))
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command("git", args...)
|
cmd := exec.Command("git", args...)
|
||||||
|
|
||||||
absPath, err := filepath.Abs(source)
|
absPath, err := filepath.Abs(source)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_DIR=%s", filepath.Join(absPath, ".git")))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_DIR=%s", filepath.Join(absPath, ".git")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.executeCommand(ctx, cmd)
|
return c.executeCommand(ctx, source, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unstaged parses the output of the `git diff` command for the `source` path.
|
// Unstaged parses the output of the `git diff` command for the `source` path.
|
||||||
@@ -151,11 +146,11 @@ func (c *Parser) Unstaged(ctx context.Context, source string) (chan Commit, erro
|
|||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_DIR=%s", filepath.Join(absPath, ".git")))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_DIR=%s", filepath.Join(absPath, ".git")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.executeCommand(ctx, cmd)
|
return c.executeCommand(ctx, source, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// executeCommand runs an exec.Cmd, reads stdout and stderr, and waits for the Cmd to complete.
|
// executeCommand runs an exec.Cmd, reads stdout and stderr, and waits for the Cmd to complete.
|
||||||
func (c *Parser) executeCommand(ctx context.Context, cmd *exec.Cmd) (chan Commit, error) {
|
func (c *Parser) executeCommand(ctx context.Context, source string, cmd *exec.Cmd) (chan Commit, error) {
|
||||||
commitChan := make(chan Commit, 64)
|
commitChan := make(chan Commit, 64)
|
||||||
|
|
||||||
stdOut, err := cmd.StdoutPipe()
|
stdOut, err := cmd.StdoutPipe()
|
||||||
@@ -180,7 +175,7 @@ func (c *Parser) executeCommand(ctx context.Context, cmd *exec.Cmd) (chan Commit
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
c.fromReader(ctx, stdOut, commitChan)
|
c.fromReader(ctx, source, stdOut, commitChan)
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
ctx.Logger().V(2).Info("Error waiting for git command to complete.", "error", err)
|
ctx.Logger().V(2).Info("Error waiting for git command to complete.", "error", err)
|
||||||
}
|
}
|
||||||
@@ -189,11 +184,12 @@ func (c *Parser) executeCommand(ctx context.Context, cmd *exec.Cmd) (chan Commit
|
|||||||
return commitChan, nil
|
return commitChan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Parser) fromReader(ctx context.Context, stdOut io.Reader, commitChan chan Commit) {
|
func (c *Parser) fromReader(ctx context.Context, source string, stdOut io.Reader, commitChan chan Commit) {
|
||||||
outReader := bufio.NewReader(stdOut)
|
outReader := bufio.NewReader(stdOut)
|
||||||
var currentCommit *Commit
|
var currentCommit *Commit
|
||||||
var currentDiff *Diff
|
var currentDiff *Diff
|
||||||
|
|
||||||
|
lastCommit := ""
|
||||||
defer common.RecoverWithExit(ctx)
|
defer common.RecoverWithExit(ctx)
|
||||||
defer close(commitChan)
|
defer close(commitChan)
|
||||||
for {
|
for {
|
||||||
@@ -204,6 +200,143 @@ func (c *Parser) fromReader(ctx context.Context, stdOut io.Reader, commitChan ch
|
|||||||
if err != nil && len(line) == 0 {
|
if err != nil && len(line) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// for i := 0; i < len(line); i++ {
|
||||||
|
// b := make([]byte, 1)
|
||||||
|
// n, err := stdOut.Read(b)
|
||||||
|
// if errors.Is(err, io.EOF) || n == 0 {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// line[i] = b[0]
|
||||||
|
// if b[0] == byte('\n') {
|
||||||
|
// line = line[:0]
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isCommitLine(line):
|
||||||
|
// If there is a currentDiff, add it to currentCommit.
|
||||||
|
if currentDiff != nil && currentDiff.Content.Len() > 0 {
|
||||||
|
currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff)
|
||||||
|
}
|
||||||
|
// If there is a currentCommit, send it to the channel.
|
||||||
|
if currentCommit != nil {
|
||||||
|
args := []string{"-C", source, "diff", "--date=format:%a %b %d %H:%M:%S %Y %z", currentCommit.Hash}
|
||||||
|
if lastCommit != "" {
|
||||||
|
args = append(args, lastCommit)
|
||||||
|
}
|
||||||
|
lastCommit = currentCommit.Hash
|
||||||
|
|
||||||
|
cmd := exec.Command("git", args...)
|
||||||
|
|
||||||
|
absPath, err := filepath.Abs(source)
|
||||||
|
if err == nil {
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_DIR=%s", filepath.Join(absPath, ".git")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// stdnOut, err := cmd.StdoutPipe()
|
||||||
|
// if err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = cmd.Wait()
|
||||||
|
//c.funkReader(ctx, stdnOut, commitChan, currentCommit)
|
||||||
|
}
|
||||||
|
// Create a new currentDiff and currentCommit
|
||||||
|
currentDiff = &Diff{}
|
||||||
|
currentCommit = &Commit{
|
||||||
|
Message: strings.Builder{},
|
||||||
|
}
|
||||||
|
// Check that the commit line contains a hash and set it.
|
||||||
|
if len(line) >= 47 {
|
||||||
|
currentCommit.Hash = string(line[7:47])
|
||||||
|
}
|
||||||
|
case isAuthorLine(line):
|
||||||
|
currentCommit.Author = strings.TrimRight(string(line[8:]), "\n")
|
||||||
|
case isDateLine(line):
|
||||||
|
date, err := time.Parse(c.dateFormat, strings.TrimSpace(string(line[6:])))
|
||||||
|
if err != nil {
|
||||||
|
ctx.Logger().V(2).Info("Could not parse date from git stream.", "error", err)
|
||||||
|
}
|
||||||
|
currentCommit.Date = date
|
||||||
|
case isModeLine(line):
|
||||||
|
// NoOp
|
||||||
|
case isIndexLine(line):
|
||||||
|
// NoOp
|
||||||
|
case isPlusFileLine(line):
|
||||||
|
currentDiff.PathB = strings.TrimRight(strings.TrimRight(string(line[6:]), "\n"), "\t") // Trim the newline and tab characters. https://github.com/trufflesecurity/trufflehog/issues/1060
|
||||||
|
case isMinusFileLine(line):
|
||||||
|
// NoOp
|
||||||
|
case isPlusDiffLine(line):
|
||||||
|
currentDiff.Content.Write(line[1:])
|
||||||
|
case isMinusDiffLine(line):
|
||||||
|
// NoOp. We only care about additions.
|
||||||
|
case isMessageLine(line):
|
||||||
|
currentCommit.Message.Write(line[4:])
|
||||||
|
case isContextDiffLine(line):
|
||||||
|
currentDiff.Content.Write([]byte("\n"))
|
||||||
|
case isBinaryLine(line):
|
||||||
|
currentDiff.IsBinary = true
|
||||||
|
currentDiff.PathB = pathFromBinaryLine(line)
|
||||||
|
case isLineNumberDiffLine(line):
|
||||||
|
if currentDiff != nil && currentDiff.Content.Len() > 0 {
|
||||||
|
currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff)
|
||||||
|
}
|
||||||
|
newDiff := &Diff{
|
||||||
|
PathB: currentDiff.PathB,
|
||||||
|
}
|
||||||
|
|
||||||
|
currentDiff = newDiff
|
||||||
|
|
||||||
|
words := bytes.Split(line, []byte(" "))
|
||||||
|
if len(words) >= 3 {
|
||||||
|
startSlice := bytes.Split(words[2], []byte(","))
|
||||||
|
lineStart, err := strconv.Atoi(string(startSlice[0]))
|
||||||
|
if err == nil {
|
||||||
|
currentDiff.LineStart = lineStart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if currentDiff.Content.Len() > c.maxDiffSize {
|
||||||
|
ctx.Logger().V(2).Info(fmt.Sprintf(
|
||||||
|
"Diff for %s exceeded MaxDiffSize(%d)", currentDiff.PathB, c.maxDiffSize,
|
||||||
|
))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanupParse(currentCommit, currentDiff, commitChan)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Parser) funkReader(ctx context.Context, stdOut io.Reader, commitChan chan Commit, currentCommit *Commit) {
|
||||||
|
outReader := bufio.NewReader(stdOut)
|
||||||
|
var currentDiff *Diff
|
||||||
|
|
||||||
|
defer common.RecoverWithExit(ctx)
|
||||||
|
for {
|
||||||
|
if common.IsDone(ctx) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
line, err := outReader.ReadBytes([]byte("\n")[0])
|
||||||
|
if err != nil && len(line) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// for i := 0; i < len(line); i++ {
|
||||||
|
// b := make([]byte, 1)
|
||||||
|
// n, err := stdOut.Read(b)
|
||||||
|
// if errors.Is(err, io.EOF) || n == 0 {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// line[i] = b[0]
|
||||||
|
// if b[0] == byte('\n') {
|
||||||
|
// line = line[:0]
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case isCommitLine(line):
|
case isCommitLine(line):
|
||||||
// If there is a currentDiff, add it to currentCommit.
|
// If there is a currentDiff, add it to currentCommit.
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
package output
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
||||||
)
|
|
||||||
|
|
||||||
var dedupeCache = make(map[string]struct{})
|
|
||||||
|
|
||||||
func PrintGitHubActionsOutput(r *detectors.ResultWithMetadata) error {
|
|
||||||
out := gitHubActionsOutputFormat{
|
|
||||||
DetectorType: r.Result.DetectorType.String(),
|
|
||||||
DecoderType: r.Result.DecoderType.String(),
|
|
||||||
Verified: r.Result.Verified,
|
|
||||||
}
|
|
||||||
|
|
||||||
meta, err := structToMap(r.SourceMetadata.Data)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not marshal result: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, data := range meta {
|
|
||||||
for k, v := range data {
|
|
||||||
if k == "line" {
|
|
||||||
if line, ok := v.(float64); ok {
|
|
||||||
out.StartLine = int64(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if k == "file" {
|
|
||||||
if filename, ok := v.(string); ok {
|
|
||||||
out.Filename = filename
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifiedStatus := "unverified"
|
|
||||||
if out.Verified {
|
|
||||||
verifiedStatus = "verified"
|
|
||||||
}
|
|
||||||
|
|
||||||
key := fmt.Sprintf("%s:%s:%s:%s:%d", out.DecoderType, out.DetectorType, verifiedStatus, out.Filename, out.StartLine)
|
|
||||||
h := sha256.New()
|
|
||||||
h.Write([]byte(key))
|
|
||||||
key = hex.EncodeToString(h.Sum(nil))
|
|
||||||
if _, ok := dedupeCache[key]; ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
dedupeCache[key] = struct{}{}
|
|
||||||
|
|
||||||
message := fmt.Sprintf("Found %s %s result 🐷🔑\n", verifiedStatus, out.DetectorType)
|
|
||||||
if r.Result.DecoderType != detectorspb.DecoderType_PLAIN {
|
|
||||||
message = fmt.Sprintf("Found %s %s result with %s encoding 🐷🔑\n", verifiedStatus, out.DetectorType, out.DecoderType)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("::warning file=%s,line=%d,endLine=%d::%s",
|
|
||||||
out.Filename, out.StartLine, out.StartLine, message)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitHubActionsOutputFormat struct {
|
|
||||||
DetectorType,
|
|
||||||
DecoderType string
|
|
||||||
Verified bool
|
|
||||||
StartLine int64
|
|
||||||
Filename string
|
|
||||||
}
|
|
||||||
@@ -386,7 +386,6 @@ type Oauth2 struct {
|
|||||||
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||||
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
|
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
|
||||||
ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
|
ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
|
||||||
AccessToken string `protobuf:"bytes,4,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Oauth2) Reset() {
|
func (x *Oauth2) Reset() {
|
||||||
@@ -442,13 +441,6 @@ func (x *Oauth2) GetClientSecret() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Oauth2) GetAccessToken() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.AccessToken
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeySecret struct {
|
type KeySecret struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -789,49 +781,47 @@ var file_credentials_proto_rawDesc = []byte{
|
|||||||
0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x65, 0x72, 0x74,
|
0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x65, 0x72, 0x74,
|
||||||
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||||
0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x92, 0x01, 0x0a, 0x06,
|
0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x6f, 0x0a, 0x06, 0x4f,
|
||||||
0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73,
|
0x61, 0x75, 0x74, 0x68, 0x32, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
|
||||||
0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72,
|
0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65,
|
||||||
0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63,
|
0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
|
||||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63,
|
||||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65,
|
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
|
||||||
0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x21, 0x0a,
|
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x35, 0x0a, 0x09,
|
||||||
0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20,
|
0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73,
|
||||||
0x22, 0x35, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x10, 0x0a,
|
0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63,
|
||||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
0x72, 0x65, 0x74, 0x22, 0x47, 0x0a, 0x03, 0x41, 0x57, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||||
0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
|
||||||
0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x47, 0x0a, 0x03, 0x41, 0x57, 0x53, 0x12, 0x10,
|
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65,
|
||||||
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x03,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x22, 0x65, 0x0a, 0x03,
|
||||||
0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69,
|
0x53, 0x45, 0x53, 0x12, 0x26, 0x0a, 0x05, 0x63, 0x72, 0x65, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e,
|
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
|
||||||
0x22, 0x65, 0x0a, 0x03, 0x53, 0x45, 0x53, 0x12, 0x26, 0x0a, 0x05, 0x63, 0x72, 0x65, 0x64, 0x73,
|
0x2e, 0x41, 0x57, 0x53, 0x52, 0x05, 0x63, 0x72, 0x65, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x6e,
|
||||||
0x69, 0x61, 0x6c, 0x73, 0x2e, 0x41, 0x57, 0x53, 0x52, 0x05, 0x63, 0x72, 0x65, 0x64, 0x73, 0x12,
|
0x64, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
|
||||||
0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65,
|
||||||
0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70,
|
0x6e, 0x74, 0x73, 0x22, 0x6c, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x70, 0x70,
|
||||||
0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x63,
|
0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18,
|
||||||
0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x6c, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x48, 0x75,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65,
|
||||||
0x62, 0x41, 0x70, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
|
0x79, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f,
|
||||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61,
|
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74,
|
||||||
0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
|
0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
|
0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49,
|
||||||
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15,
|
0x64, 0x22, 0x6a, 0x0a, 0x0b, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73,
|
||||||
0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20,
|
||||||
0x61, 0x70, 0x70, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x0b, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f,
|
0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a,
|
||||||
0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
|
0x09, 0x62, 0x6f, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x70, 0x54, 0x6f, 0x6b, 0x65,
|
0x52, 0x08, 0x62, 0x6f, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c,
|
||||||
0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6f, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02,
|
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x6f, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21,
|
0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x3f, 0x5a,
|
||||||
0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03,
|
0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65,
|
0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66,
|
||||||
0x6e, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62,
|
||||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f,
|
0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x70, 0x62, 0x62, 0x06,
|
||||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x67, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
|
|
||||||
0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -783,8 +783,6 @@ func (m *Oauth2) validate(all bool) error {
|
|||||||
|
|
||||||
// no validation rules for ClientSecret
|
// no validation rules for ClientSecret
|
||||||
|
|
||||||
// no validation rules for AccessToken
|
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
return Oauth2MultiError(errors)
|
return Oauth2MultiError(errors)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -973,13 +973,6 @@ const (
|
|||||||
DetectorType_Shopify DetectorType = 902
|
DetectorType_Shopify DetectorType = 902
|
||||||
DetectorType_RabbitMQ DetectorType = 903
|
DetectorType_RabbitMQ DetectorType = 903
|
||||||
DetectorType_CustomRegex DetectorType = 904
|
DetectorType_CustomRegex DetectorType = 904
|
||||||
DetectorType_Etherscan DetectorType = 905
|
|
||||||
DetectorType_Infura DetectorType = 906
|
|
||||||
DetectorType_Alchemy DetectorType = 907
|
|
||||||
DetectorType_BlockNative DetectorType = 908
|
|
||||||
DetectorType_Moralis DetectorType = 909
|
|
||||||
DetectorType_BscScan DetectorType = 910
|
|
||||||
DetectorType_CoinMarketCap DetectorType = 911
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for DetectorType.
|
// Enum value maps for DetectorType.
|
||||||
@@ -1886,13 +1879,6 @@ var (
|
|||||||
902: "Shopify",
|
902: "Shopify",
|
||||||
903: "RabbitMQ",
|
903: "RabbitMQ",
|
||||||
904: "CustomRegex",
|
904: "CustomRegex",
|
||||||
905: "Etherscan",
|
|
||||||
906: "Infura",
|
|
||||||
907: "Alchemy",
|
|
||||||
908: "BlockNative",
|
|
||||||
909: "Moralis",
|
|
||||||
910: "BscScan",
|
|
||||||
911: "CoinMarketCap",
|
|
||||||
}
|
}
|
||||||
DetectorType_value = map[string]int32{
|
DetectorType_value = map[string]int32{
|
||||||
"Alibaba": 0,
|
"Alibaba": 0,
|
||||||
@@ -2796,13 +2782,6 @@ var (
|
|||||||
"Shopify": 902,
|
"Shopify": 902,
|
||||||
"RabbitMQ": 903,
|
"RabbitMQ": 903,
|
||||||
"CustomRegex": 904,
|
"CustomRegex": 904,
|
||||||
"Etherscan": 905,
|
|
||||||
"Infura": 906,
|
|
||||||
"Alchemy": 907,
|
|
||||||
"BlockNative": 908,
|
|
||||||
"Moralis": 909,
|
|
||||||
"BscScan": 910,
|
|
||||||
"CoinMarketCap": 911,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3167,7 +3146,7 @@ var file_detectors_proto_rawDesc = []byte{
|
|||||||
0x0a, 0x0b, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
|
0x0a, 0x0b, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
|
||||||
0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x4c,
|
0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x4c,
|
||||||
0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x41, 0x53, 0x45, 0x36, 0x34, 0x10,
|
0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x41, 0x53, 0x45, 0x36, 0x34, 0x10,
|
||||||
0x02, 0x2a, 0xfe, 0x71, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79,
|
0x02, 0x2a, 0x91, 0x71, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79,
|
||||||
0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x10, 0x00, 0x12,
|
0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x10, 0x00, 0x12,
|
||||||
0x08, 0x0a, 0x04, 0x41, 0x4d, 0x51, 0x50, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x57, 0x53,
|
0x08, 0x0a, 0x04, 0x41, 0x4d, 0x51, 0x50, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x57, 0x53,
|
||||||
0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x10, 0x03, 0x12, 0x0a, 0x0a,
|
0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x10, 0x03, 0x12, 0x0a, 0x0a,
|
||||||
@@ -4072,18 +4051,11 @@ var file_detectors_proto_rawDesc = []byte{
|
|||||||
0x44, 0x41, 0x50, 0x10, 0x85, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x6f, 0x70, 0x69, 0x66,
|
0x44, 0x41, 0x50, 0x10, 0x85, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x6f, 0x70, 0x69, 0x66,
|
||||||
0x79, 0x10, 0x86, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x4d, 0x51,
|
0x79, 0x10, 0x86, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x4d, 0x51,
|
||||||
0x10, 0x87, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x67,
|
0x10, 0x87, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x67,
|
||||||
0x65, 0x78, 0x10, 0x88, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x74, 0x68, 0x65, 0x72, 0x73, 0x63,
|
0x65, 0x78, 0x10, 0x88, 0x07, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||||
0x61, 0x6e, 0x10, 0x89, 0x07, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x6e, 0x66, 0x75, 0x72, 0x61, 0x10,
|
0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72,
|
||||||
0x8a, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x6c, 0x63, 0x68, 0x65, 0x6d, 0x79, 0x10, 0x8b, 0x07,
|
0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76,
|
||||||
0x12, 0x10, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x10,
|
0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f,
|
||||||
0x8c, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x6f, 0x72, 0x61, 0x6c, 0x69, 0x73, 0x10, 0x8d, 0x07,
|
0x72, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x12, 0x0c, 0x0a, 0x07, 0x42, 0x73, 0x63, 0x53, 0x63, 0x61, 0x6e, 0x10, 0x8e, 0x07, 0x12, 0x12,
|
|
||||||
0x0a, 0x0d, 0x43, 0x6f, 0x69, 0x6e, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x43, 0x61, 0x70, 0x10,
|
|
||||||
0x8f, 0x07, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
|
|
||||||
0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70,
|
|
||||||
0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x70,
|
|
||||||
0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -1185,14 +1185,10 @@ type GCS struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Bucket string `protobuf:"bytes,1,opt,name=bucket,proto3" json:"bucket,omitempty"`
|
Bucket string `protobuf:"bytes,1,opt,name=bucket,proto3" json:"bucket,omitempty"`
|
||||||
Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"`
|
File string `protobuf:"bytes,2,opt,name=file,proto3" json:"file,omitempty"`
|
||||||
Link string `protobuf:"bytes,3,opt,name=link,proto3" json:"link,omitempty"`
|
Link string `protobuf:"bytes,3,opt,name=link,proto3" json:"link,omitempty"`
|
||||||
Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
|
Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
|
||||||
CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
|
|
||||||
Acls []string `protobuf:"bytes,7,rep,name=acls,proto3" json:"acls,omitempty"`
|
|
||||||
ContentType string `protobuf:"bytes,8,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) Reset() {
|
func (x *GCS) Reset() {
|
||||||
@@ -1234,9 +1230,9 @@ func (x *GCS) GetBucket() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) GetFilename() string {
|
func (x *GCS) GetFile() string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Filename
|
return x.File
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -1255,34 +1251,6 @@ func (x *GCS) GetEmail() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) GetCreatedAt() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CreatedAt
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetUpdatedAt() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.UpdatedAt
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetAcls() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Acls
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetContentType() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.ContentType
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type Jira struct {
|
type Jira struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -2793,220 +2761,212 @@ var file_source_metadata_proto_rawDesc = []byte{
|
|||||||
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x12,
|
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x12,
|
||||||
0x28, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64,
|
0x28, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64,
|
||||||
0x5f, 0x62, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x4d,
|
0x5f, 0x62, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x4d,
|
||||||
0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x79, 0x22, 0xd8, 0x01, 0x0a, 0x03, 0x47, 0x43,
|
0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x79, 0x22, 0x5b, 0x0a, 0x03, 0x47, 0x43, 0x53,
|
||||||
0x53, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x09, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c,
|
0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65,
|
||||||
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20,
|
0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61,
|
0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12,
|
0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x98, 0x01, 0x0a, 0x04, 0x4a, 0x69, 0x72, 0x61, 0x12,
|
||||||
0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20,
|
0x14, 0x0a, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d,
|
0x69, 0x73, 0x73, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18,
|
||||||
0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01,
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x12, 0x0a,
|
||||||
0x28, 0x09, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x12, 0x0a,
|
|
||||||
0x04, 0x61, 0x63, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x63, 0x6c,
|
|
||||||
0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70,
|
|
||||||
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
|
||||||
0x54, 0x79, 0x70, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x04, 0x4a, 0x69, 0x72, 0x61, 0x12, 0x14, 0x0a,
|
|
||||||
0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x73,
|
|
||||||
0x73, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6c,
|
|
||||||
0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12,
|
|
||||||
0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65,
|
|
||||||
0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69,
|
|
||||||
0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22,
|
|
||||||
0x77, 0x0a, 0x03, 0x4e, 0x50, 0x4d, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61,
|
|
||||||
0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63,
|
|
||||||
0x6b, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18,
|
|
||||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12,
|
|
||||||
0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69,
|
|
||||||
0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x78, 0x0a, 0x04, 0x50, 0x79, 0x50, 0x69,
|
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
|
||||||
0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18,
|
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x18,
|
|
||||||
0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
|
||||||
0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b,
|
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05,
|
|
||||||
0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61,
|
|
||||||
0x69, 0x6c, 0x22, 0x78, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b,
|
|
||||||
0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74,
|
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
|
||||||
0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01,
|
|
||||||
0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69,
|
|
||||||
0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1c,
|
|
||||||
0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x97, 0x02, 0x0a,
|
|
||||||
0x05, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
|
||||||
0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e,
|
|
||||||
0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
|
||||||
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61,
|
|
||||||
0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
|
||||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d,
|
|
||||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69,
|
|
||||||
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12,
|
|
||||||
0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c,
|
|
||||||
0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
|
||||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x3b, 0x0a,
|
|
||||||
0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28,
|
|
||||||
0x0e, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a,
|
|
||||||
0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f,
|
|
||||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f,
|
|
||||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x72, 0x72, 0x69,
|
|
||||||
0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c,
|
|
||||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a,
|
|
||||||
0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d,
|
|
||||||
0x61, 0x69, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1c, 0x0a,
|
|
||||||
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
|
||||||
0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6c,
|
|
||||||
0x69, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x22,
|
|
||||||
0x1a, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
|
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x07,
|
|
||||||
0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65,
|
|
||||||
0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
|
|
||||||
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x75,
|
|
||||||
0x69, 0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
|
|
||||||
0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a,
|
|
||||||
0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e,
|
0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e,
|
||||||
0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04,
|
0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22,
|
0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a,
|
||||||
0xda, 0x01, 0x0a, 0x05, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61,
|
0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d,
|
||||||
0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
|
0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e,
|
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||||
0x6e, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
0x70, 0x22, 0x77, 0x0a, 0x03, 0x4e, 0x50, 0x4d, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65,
|
||||||
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
||||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70,
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65,
|
0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
|
||||||
0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72,
|
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
|
||||||
0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||||
0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x06,
|
0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d,
|
0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x78, 0x0a, 0x04, 0x50, 0x79,
|
||||||
0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
0x50, 0x69, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01,
|
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
|
||||||
0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x99, 0x01, 0x0a,
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
|
||||||
0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04,
|
0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f,
|
0x09, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14,
|
||||||
0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01,
|
0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65,
|
||||||
0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
0x6d, 0x61, 0x69, 0x6c, 0x22, 0x78, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75,
|
||||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d,
|
0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b,
|
||||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
|
0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
|
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03,
|
||||||
0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d,
|
||||||
0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0xa8, 0x01, 0x0a, 0x06, 0x53, 0x79, 0x73,
|
0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
||||||
0x6c, 0x6f, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12,
|
0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x97,
|
||||||
0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
0x02, 0x0a, 0x05, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e,
|
||||||
0x52, 0x07, 0x61, 0x70, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f,
|
0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68,
|
||||||
0x63, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x63, 0x69,
|
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04,
|
0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
|
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
|
||||||
0x16, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74,
|
||||||
0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x61, 0x63, 0x69, 0x6c,
|
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72,
|
||||||
0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x61, 0x63, 0x69, 0x6c,
|
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49,
|
||||||
0x69, 0x74, 0x79, 0x22, 0x56, 0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65,
|
0x64, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x0a, 0x06,
|
0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x06, 0x20,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47,
|
0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12,
|
||||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x42,
|
0x3b, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20,
|
||||||
0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x87, 0x0a, 0x0a, 0x08,
|
0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74,
|
||||||
0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x7a, 0x75, 0x72,
|
0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79,
|
||||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x48,
|
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||||
0x00, 0x52, 0x05, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x62, 0x69, 0x74, 0x62,
|
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x72,
|
||||||
0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x6f,
|
0x72, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20,
|
||||||
0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x42, 0x69,
|
0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66,
|
||||||
0x74, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x62, 0x69, 0x74, 0x62, 0x75,
|
0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x12, 0x37, 0x0a, 0x08, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x63, 0x69,
|
0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
|
||||||
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x43,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12,
|
||||||
0x49, 0x48, 0x00, 0x52, 0x08, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x63, 0x69, 0x12, 0x3d, 0x0a,
|
0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01,
|
||||||
0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x12, 0x0a,
|
||||||
0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x6c, 0x69, 0x6e,
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00,
|
0x65, 0x22, 0x1a, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c,
|
||||||
0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3a, 0x0a, 0x09,
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x81, 0x01,
|
||||||
0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x0a, 0x07, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
|
||||||
0x1a, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x61, 0x2e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52, 0x09, 0x64,
|
0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c,
|
||||||
0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x12, 0x28, 0x0a, 0x03, 0x65, 0x63, 0x72, 0x18,
|
0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d,
|
0x28, 0x03, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12,
|
||||||
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x43, 0x52, 0x48, 0x00, 0x52, 0x03, 0x65,
|
0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c,
|
||||||
0x63, 0x72, 0x12, 0x28, 0x0a, 0x03, 0x67, 0x63, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x69, 0x6e, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||||
0x14, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||||
0x61, 0x2e, 0x47, 0x43, 0x53, 0x48, 0x00, 0x52, 0x03, 0x67, 0x63, 0x73, 0x12, 0x31, 0x0a, 0x06,
|
0x70, 0x22, 0xda, 0x01, 0x0a, 0x05, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73,
|
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47,
|
0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68,
|
||||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x12,
|
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x31, 0x0a, 0x06, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a,
|
||||||
0x17, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x61, 0x2e, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69, 0x74, 0x6c,
|
0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x75,
|
||||||
0x61, 0x62, 0x12, 0x2b, 0x0a, 0x04, 0x6a, 0x69, 0x72, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
|
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73,
|
||||||
0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01,
|
||||||
0x74, 0x61, 0x2e, 0x4a, 0x69, 0x72, 0x61, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x69, 0x72, 0x61, 0x12,
|
0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65,
|
||||||
0x28, 0x0a, 0x03, 0x6e, 0x70, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73,
|
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4e,
|
0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61,
|
||||||
0x50, 0x4d, 0x48, 0x00, 0x52, 0x03, 0x6e, 0x70, 0x6d, 0x12, 0x2b, 0x0a, 0x04, 0x70, 0x79, 0x70,
|
0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08,
|
||||||
0x69, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x99,
|
||||||
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x79, 0x50, 0x69, 0x48, 0x00,
|
0x01, 0x0a, 0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12,
|
||||||
0x52, 0x04, 0x70, 0x79, 0x70, 0x69, 0x12, 0x25, 0x0a, 0x02, 0x73, 0x33, 0x18, 0x0d, 0x20, 0x01,
|
0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65,
|
||||||
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
|
0x70, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x33, 0x48, 0x00, 0x52, 0x02, 0x73, 0x33, 0x12, 0x2e, 0x0a,
|
0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03,
|
||||||
0x05, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53,
|
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74,
|
||||||
0x6c, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x3d, 0x0a,
|
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72,
|
||||||
0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x0f, 0x20, 0x01, 0x28,
|
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
|
||||||
0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20,
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x48, 0x00,
|
0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0xa8, 0x01, 0x0a, 0x06, 0x53,
|
||||||
0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x28, 0x0a, 0x03,
|
0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d,
|
||||||
0x67, 0x69, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x6f, 0x75, 0x72,
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d,
|
||||||
0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x69, 0x74, 0x48,
|
0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x00, 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0x11,
|
0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65,
|
0x72, 0x6f, 0x63, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x74,
|
0x63, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||||
0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x65,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
0x70, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69,
|
0x09, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x61, 0x63,
|
||||||
0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x65, 0x12,
|
0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x61, 0x63,
|
||||||
0x31, 0x0a, 0x06, 0x67, 0x65, 0x72, 0x72, 0x69, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x56, 0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45,
|
||||||
0x17, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x31,
|
||||||
0x61, 0x2e, 0x47, 0x65, 0x72, 0x72, 0x69, 0x74, 0x48, 0x00, 0x52, 0x06, 0x67, 0x65, 0x72, 0x72,
|
0x0a, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
|
||||||
0x69, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x6a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x18, 0x14, 0x20,
|
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74,
|
0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x48, 0x00, 0x52,
|
0x62, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x87, 0x0a,
|
||||||
0x07, 0x6a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x65, 0x61, 0x6d,
|
0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x7a,
|
||||||
0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x6f, 0x75, 0x72,
|
||||||
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x48,
|
0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x7a, 0x75, 0x72,
|
||||||
0x00, 0x52, 0x05, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x40, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69,
|
0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x62, 0x69,
|
||||||
0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
0x74, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
|
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
|
||||||
0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x48, 0x00, 0x52, 0x0b, 0x61,
|
0x42, 0x69, 0x74, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x62, 0x69, 0x74,
|
||||||
0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x79,
|
0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x37, 0x0a, 0x08, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65,
|
||||||
0x73, 0x6c, 0x6f, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x6f, 0x75,
|
0x63, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||||
0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x79, 0x73,
|
0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x6c,
|
||||||
0x6c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x06, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12, 0x5e, 0x0a,
|
0x65, 0x43, 0x49, 0x48, 0x00, 0x52, 0x08, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x63, 0x69, 0x12,
|
||||||
0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69,
|
0x3d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20,
|
||||||
0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73,
|
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50,
|
0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65,
|
||||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
|
0x48, 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3a,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76,
|
0x0a, 0x09, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x0a,
|
0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x2a, 0x3e, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c,
|
0x61, 0x74, 0x61, 0x2e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52,
|
||||||
0x69, 0x74, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x10, 0x00, 0x12,
|
0x09, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x12, 0x28, 0x0a, 0x03, 0x65, 0x63,
|
||||||
0x0b, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06,
|
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||||
0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x75, 0x6e, 0x6b, 0x6e,
|
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x43, 0x52, 0x48, 0x00, 0x52,
|
||||||
0x6f, 0x77, 0x6e, 0x10, 0x03, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x03, 0x65, 0x63, 0x72, 0x12, 0x28, 0x0a, 0x03, 0x67, 0x63, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72,
|
0x0b, 0x32, 0x14, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||||
0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76,
|
0x61, 0x74, 0x61, 0x2e, 0x47, 0x43, 0x53, 0x48, 0x00, 0x52, 0x03, 0x67, 0x63, 0x73, 0x12, 0x31,
|
||||||
0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
0x0a, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
|
||||||
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
0x6f, 0x33,
|
0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
|
0x62, 0x12, 0x31, 0x0a, 0x06, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x17, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x2e, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x48, 0x00, 0x52, 0x06, 0x67, 0x69,
|
||||||
|
0x74, 0x6c, 0x61, 0x62, 0x12, 0x2b, 0x0a, 0x04, 0x6a, 0x69, 0x72, 0x61, 0x18, 0x0a, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
|
||||||
|
0x64, 0x61, 0x74, 0x61, 0x2e, 0x4a, 0x69, 0x72, 0x61, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x69, 0x72,
|
||||||
|
0x61, 0x12, 0x28, 0x0a, 0x03, 0x6e, 0x70, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14,
|
||||||
|
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
|
0x2e, 0x4e, 0x50, 0x4d, 0x48, 0x00, 0x52, 0x03, 0x6e, 0x70, 0x6d, 0x12, 0x2b, 0x0a, 0x04, 0x70,
|
||||||
|
0x79, 0x70, 0x69, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72,
|
||||||
|
0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x79, 0x50, 0x69,
|
||||||
|
0x48, 0x00, 0x52, 0x04, 0x70, 0x79, 0x70, 0x69, 0x12, 0x25, 0x0a, 0x02, 0x73, 0x33, 0x18, 0x0d,
|
||||||
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65,
|
||||||
|
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x33, 0x48, 0x00, 0x52, 0x02, 0x73, 0x33, 0x12,
|
||||||
|
0x2e, 0x0a, 0x05, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
|
||||||
|
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
|
0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x12,
|
||||||
|
0x3d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x0f, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74,
|
||||||
|
0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
|
||||||
|
0x48, 0x00, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x28,
|
||||||
|
0x0a, 0x03, 0x67, 0x69, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x6f,
|
||||||
|
0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x69,
|
||||||
|
0x74, 0x48, 0x00, 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74,
|
||||||
|
0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
||||||
|
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52,
|
||||||
|
0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69,
|
||||||
|
0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||||
|
0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64,
|
||||||
|
0x6b, 0x69, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74,
|
||||||
|
0x65, 0x12, 0x31, 0x0a, 0x06, 0x67, 0x65, 0x72, 0x72, 0x69, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x17, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x72, 0x72, 0x69, 0x74, 0x48, 0x00, 0x52, 0x06, 0x67, 0x65,
|
||||||
|
0x72, 0x72, 0x69, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x6a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x18,
|
||||||
|
0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d,
|
||||||
|
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x48,
|
||||||
|
0x00, 0x52, 0x07, 0x6a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x65,
|
||||||
|
0x61, 0x6d, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x6f, 0x75, 0x72,
|
||||||
|
0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x61, 0x6d,
|
||||||
|
0x73, 0x48, 0x00, 0x52, 0x05, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x40, 0x0a, 0x0b, 0x61, 0x72,
|
||||||
|
0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
|
0x1c, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||||
|
0x61, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x48, 0x00, 0x52,
|
||||||
|
0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x06,
|
||||||
|
0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73,
|
||||||
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53,
|
||||||
|
0x79, 0x73, 0x6c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x06, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12,
|
||||||
|
0x5e, 0x0a, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f,
|
||||||
|
0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
|
||||||
|
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
|
0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69,
|
||||||
|
0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||||
|
0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x42,
|
||||||
|
0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x2a, 0x3e, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62,
|
||||||
|
0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x10,
|
||||||
|
0x00, 0x12, 0x0b, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x10, 0x01, 0x12, 0x0a,
|
||||||
|
0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x75, 0x6e,
|
||||||
|
0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x03, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
|
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63,
|
||||||
|
0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67,
|
||||||
|
0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||||
|
0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -1401,18 +1401,12 @@ func (m *GCS) validate(all bool) error {
|
|||||||
|
|
||||||
// no validation rules for Bucket
|
// no validation rules for Bucket
|
||||||
|
|
||||||
// no validation rules for Filename
|
// no validation rules for File
|
||||||
|
|
||||||
// no validation rules for Link
|
// no validation rules for Link
|
||||||
|
|
||||||
// no validation rules for Email
|
// no validation rules for Email
|
||||||
|
|
||||||
// no validation rules for CreatedAt
|
|
||||||
|
|
||||||
// no validation rules for UpdatedAt
|
|
||||||
|
|
||||||
// no validation rules for ContentType
|
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
return GCSMultiError(errors)
|
return GCSMultiError(errors)
|
||||||
}
|
}
|
||||||
|
|||||||
+313
-466
@@ -57,7 +57,6 @@ const (
|
|||||||
SourceType_SOURCE_TYPE_PUBLIC_EVENT_MONITORING SourceType = 26
|
SourceType_SOURCE_TYPE_PUBLIC_EVENT_MONITORING SourceType = 26
|
||||||
SourceType_SOURCE_TYPE_SLACK_REALTIME SourceType = 27
|
SourceType_SOURCE_TYPE_SLACK_REALTIME SourceType = 27
|
||||||
SourceType_SOURCE_TYPE_GOOGLE_DRIVE SourceType = 28
|
SourceType_SOURCE_TYPE_GOOGLE_DRIVE SourceType = 28
|
||||||
SourceType_SOURCE_TYPE_GCS_UNAUTHED SourceType = 30
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for SourceType.
|
// Enum value maps for SourceType.
|
||||||
@@ -92,7 +91,6 @@ var (
|
|||||||
26: "SOURCE_TYPE_PUBLIC_EVENT_MONITORING",
|
26: "SOURCE_TYPE_PUBLIC_EVENT_MONITORING",
|
||||||
27: "SOURCE_TYPE_SLACK_REALTIME",
|
27: "SOURCE_TYPE_SLACK_REALTIME",
|
||||||
28: "SOURCE_TYPE_GOOGLE_DRIVE",
|
28: "SOURCE_TYPE_GOOGLE_DRIVE",
|
||||||
30: "SOURCE_TYPE_GCS_UNAUTHED",
|
|
||||||
}
|
}
|
||||||
SourceType_value = map[string]int32{
|
SourceType_value = map[string]int32{
|
||||||
"SOURCE_TYPE_AZURE_STORAGE": 0,
|
"SOURCE_TYPE_AZURE_STORAGE": 0,
|
||||||
@@ -124,7 +122,6 @@ var (
|
|||||||
"SOURCE_TYPE_PUBLIC_EVENT_MONITORING": 26,
|
"SOURCE_TYPE_PUBLIC_EVENT_MONITORING": 26,
|
||||||
"SOURCE_TYPE_SLACK_REALTIME": 27,
|
"SOURCE_TYPE_SLACK_REALTIME": 27,
|
||||||
"SOURCE_TYPE_GOOGLE_DRIVE": 28,
|
"SOURCE_TYPE_GOOGLE_DRIVE": 28,
|
||||||
"SOURCE_TYPE_GCS_UNAUTHED": 30,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -894,8 +891,8 @@ type Filesystem struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// DEPRECATED: directories is deprecated and can be removed / renamed to
|
// directories is deprecated and can be removed / renamed to paths when
|
||||||
// paths when we no longer depend on the name in enterprise configs.
|
// we no longer depend on the name in enterprise configs
|
||||||
Directories []string `protobuf:"bytes,1,rep,name=directories,proto3" json:"directories,omitempty"`
|
Directories []string `protobuf:"bytes,1,rep,name=directories,proto3" json:"directories,omitempty"`
|
||||||
Paths []string `protobuf:"bytes,2,rep,name=paths,proto3" json:"paths,omitempty"`
|
Paths []string `protobuf:"bytes,2,rep,name=paths,proto3" json:"paths,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -952,19 +949,9 @@ type GCS struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Types that are assignable to Credential:
|
// Types that are assignable to Credential:
|
||||||
// *GCS_JsonServiceAccount
|
// *GCS_JsonSa
|
||||||
// *GCS_ApiKey
|
Credential isGCS_Credential `protobuf_oneof:"credential"`
|
||||||
// *GCS_Unauthenticated
|
Buckets []string `protobuf:"bytes,2,rep,name=buckets,proto3" json:"buckets,omitempty"`
|
||||||
// *GCS_Adc
|
|
||||||
// *GCS_ServiceAccountFile
|
|
||||||
// *GCS_Oauth
|
|
||||||
Credential isGCS_Credential `protobuf_oneof:"credential"`
|
|
||||||
ProjectId string `protobuf:"bytes,5,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"`
|
|
||||||
IncludeBuckets []string `protobuf:"bytes,6,rep,name=include_buckets,json=includeBuckets,proto3" json:"include_buckets,omitempty"`
|
|
||||||
ExcludeBuckets []string `protobuf:"bytes,7,rep,name=exclude_buckets,json=excludeBuckets,proto3" json:"exclude_buckets,omitempty"`
|
|
||||||
IncludeObjects []string `protobuf:"bytes,8,rep,name=include_objects,json=includeObjects,proto3" json:"include_objects,omitempty"`
|
|
||||||
ExcludeObjects []string `protobuf:"bytes,9,rep,name=exclude_objects,json=excludeObjects,proto3" json:"exclude_objects,omitempty"`
|
|
||||||
MaxObjectSize int64 `protobuf:"varint,10,opt,name=max_object_size,json=maxObjectSize,proto3" json:"max_object_size,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) Reset() {
|
func (x *GCS) Reset() {
|
||||||
@@ -1006,129 +993,29 @@ func (m *GCS) GetCredential() isGCS_Credential {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) GetJsonServiceAccount() string {
|
func (x *GCS) GetJsonSa() string {
|
||||||
if x, ok := x.GetCredential().(*GCS_JsonServiceAccount); ok {
|
if x, ok := x.GetCredential().(*GCS_JsonSa); ok {
|
||||||
return x.JsonServiceAccount
|
return x.JsonSa
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) GetApiKey() string {
|
func (x *GCS) GetBuckets() []string {
|
||||||
if x, ok := x.GetCredential().(*GCS_ApiKey); ok {
|
|
||||||
return x.ApiKey
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetUnauthenticated() *credentialspb.Unauthenticated {
|
|
||||||
if x, ok := x.GetCredential().(*GCS_Unauthenticated); ok {
|
|
||||||
return x.Unauthenticated
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetAdc() *credentialspb.CloudEnvironment {
|
|
||||||
if x, ok := x.GetCredential().(*GCS_Adc); ok {
|
|
||||||
return x.Adc
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetServiceAccountFile() string {
|
|
||||||
if x, ok := x.GetCredential().(*GCS_ServiceAccountFile); ok {
|
|
||||||
return x.ServiceAccountFile
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetOauth() *credentialspb.Oauth2 {
|
|
||||||
if x, ok := x.GetCredential().(*GCS_Oauth); ok {
|
|
||||||
return x.Oauth
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetProjectId() string {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ProjectId
|
return x.Buckets
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetIncludeBuckets() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.IncludeBuckets
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GCS) GetExcludeBuckets() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.ExcludeBuckets
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetIncludeObjects() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.IncludeObjects
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetExcludeObjects() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.ExcludeObjects
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GCS) GetMaxObjectSize() int64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.MaxObjectSize
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type isGCS_Credential interface {
|
type isGCS_Credential interface {
|
||||||
isGCS_Credential()
|
isGCS_Credential()
|
||||||
}
|
}
|
||||||
|
|
||||||
type GCS_JsonServiceAccount struct {
|
type GCS_JsonSa struct {
|
||||||
JsonServiceAccount string `protobuf:"bytes,1,opt,name=json_service_account,json=jsonServiceAccount,proto3,oneof"`
|
JsonSa string `protobuf:"bytes,1,opt,name=json_sa,json=jsonSa,proto3,oneof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GCS_ApiKey struct {
|
func (*GCS_JsonSa) isGCS_Credential() {}
|
||||||
ApiKey string `protobuf:"bytes,2,opt,name=api_key,json=apiKey,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GCS_Unauthenticated struct {
|
|
||||||
Unauthenticated *credentialspb.Unauthenticated `protobuf:"bytes,3,opt,name=unauthenticated,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GCS_Adc struct {
|
|
||||||
Adc *credentialspb.CloudEnvironment `protobuf:"bytes,4,opt,name=adc,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GCS_ServiceAccountFile struct {
|
|
||||||
ServiceAccountFile string `protobuf:"bytes,11,opt,name=service_account_file,json=serviceAccountFile,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GCS_Oauth struct {
|
|
||||||
Oauth *credentialspb.Oauth2 `protobuf:"bytes,12,opt,name=oauth,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GCS_JsonServiceAccount) isGCS_Credential() {}
|
|
||||||
|
|
||||||
func (*GCS_ApiKey) isGCS_Credential() {}
|
|
||||||
|
|
||||||
func (*GCS_Unauthenticated) isGCS_Credential() {}
|
|
||||||
|
|
||||||
func (*GCS_Adc) isGCS_Credential() {}
|
|
||||||
|
|
||||||
func (*GCS_ServiceAccountFile) isGCS_Credential() {}
|
|
||||||
|
|
||||||
func (*GCS_Oauth) isGCS_Credential() {}
|
|
||||||
|
|
||||||
type Git struct {
|
type Git struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
@@ -2904,312 +2791,280 @@ var file_sources_proto_rawDesc = []byte{
|
|||||||
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||||
0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72,
|
0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72,
|
||||||
0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68,
|
0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68,
|
||||||
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xab,
|
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0x48,
|
||||||
0x04, 0x0a, 0x03, 0x47, 0x43, 0x53, 0x12, 0x32, 0x0a, 0x14, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73,
|
0x0a, 0x03, 0x47, 0x43, 0x53, 0x12, 0x19, 0x0a, 0x07, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x61,
|
||||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x61,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x12, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76,
|
0x12, 0x18, 0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x61, 0x70,
|
0x09, 0x52, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72,
|
||||||
0x69, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x61,
|
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x03, 0x47, 0x69, 0x74,
|
||||||
0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65,
|
0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01,
|
||||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||||
0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61,
|
0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09,
|
||||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f,
|
0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61,
|
||||||
0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
|
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x31, 0x0a, 0x03, 0x61, 0x64, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63,
|
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
|
||||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64,
|
0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
|
||||||
0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x61,
|
0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||||
0x64, 0x63, 0x12, 0x32, 0x0a, 0x14, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63,
|
0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x08, 0x73, 0x73, 0x68, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18,
|
||||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
|
0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
0x48, 0x00, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
0x61, 0x6c, 0x73, 0x2e, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x73,
|
||||||
0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18,
|
0x73, 0x68, 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||||
0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72,
|
||||||
0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61,
|
0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f,
|
||||||
0x75, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69,
|
0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c,
|
||||||
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
|
0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a,
|
||||||
0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75,
|
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x81, 0x02, 0x0a, 0x06, 0x47,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x63,
|
0x69, 0x74, 0x4c, 0x61, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||||
0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65,
|
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01,
|
||||||
0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x07,
|
0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x63,
|
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f,
|
||||||
0x6b, 0x65, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f,
|
0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01,
|
||||||
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69,
|
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
|
||||||
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x27, 0x0a,
|
0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73,
|
0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04,
|
||||||
0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||||
0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x62,
|
0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09,
|
||||||
0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52,
|
0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70,
|
||||||
0x0d, 0x6d, 0x61, 0x78, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x0c,
|
0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a,
|
0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a,
|
||||||
0x03, 0x47, 0x69, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75,
|
0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x06, 0x20,
|
||||||
0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65,
|
0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73,
|
||||||
|
0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xd1,
|
||||||
|
0x03, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64,
|
||||||
|
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05,
|
||||||
|
0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12,
|
||||||
|
0x37, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x70, 0x70, 0x18, 0x02, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||||
|
0x73, 0x2e, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x70, 0x70, 0x48, 0x00, 0x52, 0x09, 0x67,
|
||||||
|
0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65,
|
||||||
|
0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
|
||||||
|
0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||||
|
0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64,
|
||||||
|
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||||
|
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74,
|
||||||
|
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65,
|
||||||
|
0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
|
||||||
|
0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x24,
|
||||||
|
0x0a, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
|
||||||
|
0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74,
|
||||||
|
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72,
|
||||||
|
0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65,
|
||||||
|
0x72, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72,
|
||||||
|
0x6b, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
|
||||||
|
0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x09,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61,
|
||||||
|
0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x20,
|
||||||
|
0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x0b, 0x20,
|
||||||
|
0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73,
|
||||||
|
0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73,
|
||||||
|
0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52,
|
||||||
|
0x65, 0x70, 0x6f, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
|
0x61, 0x6c, 0x22, 0x42, 0x0a, 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x44, 0x72, 0x69, 0x76,
|
||||||
|
0x65, 0x12, 0x25, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b,
|
||||||
|
0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72,
|
||||||
|
0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
||||||
|
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x9e, 0x02, 0x0a, 0x04, 0x4a, 0x49, 0x52, 0x41, 0x12,
|
||||||
|
0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64,
|
||||||
|
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61,
|
||||||
|
0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64,
|
||||||
|
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74,
|
||||||
|
0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48,
|
||||||
|
0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||||
|
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||||
|
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||||
|
0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65,
|
||||||
|
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74,
|
||||||
|
0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||||
|
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05,
|
||||||
|
0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a,
|
||||||
|
0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
|
0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x73, 0x0a, 0x19, 0x4e, 0x50, 0x4d, 0x55, 0x6e,
|
||||||
|
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63,
|
||||||
|
0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||||
|
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
||||||
|
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75,
|
||||||
|
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75,
|
||||||
|
0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x0c,
|
||||||
|
0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x74, 0x0a, 0x1a,
|
||||||
|
0x50, 0x79, 0x50, 0x49, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||||
|
0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e,
|
||||||
|
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||||
|
0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||||
|
0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||||
|
0x61, 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
|
0x61, 0x6c, 0x22, 0xfd, 0x01, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x63, 0x63,
|
||||||
|
0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
|
||||||
|
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4b, 0x65, 0x79, 0x53,
|
||||||
|
0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b,
|
||||||
|
0x65, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||||
|
0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72,
|
||||||
|
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,
|
||||||
|
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61,
|
||||||
|
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x11,
|
||||||
|
0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e,
|
||||||
|
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||||
|
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72,
|
||||||
|
0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x45,
|
||||||
|
0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x75,
|
||||||
|
0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x63,
|
||||||
|
0x6b, 0x65, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
|
0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a, 0x05, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x08,
|
||||||
|
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08,
|
||||||
|
0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||||
|
0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f,
|
||||||
|
0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65,
|
||||||
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f,
|
||||||
|
0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1a,
|
||||||
|
0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
|
||||||
|
0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67,
|
||||||
|
0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a,
|
||||||
|
0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72,
|
||||||
|
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x06, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74,
|
||||||
|
0x22, 0x31, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x65, 0x12, 0x16, 0x0a,
|
||||||
|
0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05,
|
||||||
|
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||||
|
0x69, 0x61, 0x6c, 0x22, 0xdb, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x72, 0x72, 0x69, 0x74, 0x12, 0x24,
|
||||||
|
0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70,
|
||||||
|
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75,
|
||||||
|
0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68,
|
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68,
|
||||||
0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a,
|
0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a,
|
||||||
0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
|
0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||||
0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||||
0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x08, 0x73, 0x73, 0x68, 0x5f, 0x61,
|
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65,
|
||||||
0x75, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x72, 0x65, 0x64,
|
0x63, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65,
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x48,
|
0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||||
0x00, 0x52, 0x07, 0x73, 0x73, 0x68, 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69,
|
0x6c, 0x22, 0xa5, 0x01, 0x0a, 0x07, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x24, 0x0a,
|
||||||
0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
|
||||||
0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c,
|
|
||||||
0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
|
|
||||||
0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73,
|
|
||||||
0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x81,
|
|
||||||
0x02, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x4c, 0x61, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64,
|
|
||||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05,
|
|
||||||
0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12,
|
|
||||||
0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
|
||||||
0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68,
|
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
|
||||||
0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f,
|
|
||||||
0x61, 0x75, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75,
|
|
||||||
0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65,
|
|
||||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68,
|
|
||||||
0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a,
|
|
||||||
0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20,
|
|
||||||
0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65,
|
|
||||||
0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f,
|
|
||||||
0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52,
|
|
||||||
0x65, 0x70, 0x6f, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
|
||||||
0x61, 0x6c, 0x22, 0xd1, 0x03, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x12, 0x24, 0x0a,
|
|
||||||
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||||
0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
|
0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
|
||||||
0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x70,
|
0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74,
|
||||||
0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||||
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x70, 0x70, 0x48,
|
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48,
|
||||||
0x00, 0x52, 0x09, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x12, 0x16, 0x0a, 0x05,
|
0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x06,
|
||||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74,
|
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63,
|
||||||
0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65,
|
||||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x0c, 0x0a, 0x0a, 0x63,
|
||||||
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75,
|
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xf0, 0x01, 0x0a, 0x05, 0x54, 0x65,
|
||||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75,
|
0x61, 0x6d, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
|
||||||
0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22,
|
|
||||||
0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05,
|
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69,
|
|
||||||
0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e,
|
|
||||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x63, 0x61, 0x6e,
|
|
||||||
0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x63, 0x61,
|
|
||||||
0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
|
|
||||||
0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e,
|
|
||||||
0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65,
|
|
||||||
0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x12,
|
|
||||||
0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x61,
|
|
||||||
0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f,
|
|
||||||
0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52,
|
|
||||||
0x65, 0x70, 0x6f, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52,
|
|
||||||
0x65, 0x70, 0x6f, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c,
|
|
||||||
0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x42, 0x0a, 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
|
||||||
0x44, 0x72, 0x69, 0x76, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
|
|
||||||
0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c,
|
|
||||||
0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a,
|
|
||||||
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x9e, 0x02, 0x0a, 0x04, 0x4a,
|
|
||||||
0x49, 0x52, 0x41, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
|
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52,
|
||||||
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73,
|
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
|
||||||
0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
|
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65,
|
||||||
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69,
|
0x6e, 0x12, 0x46, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||||
0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75,
|
0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||||
0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65,
|
||||||
0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72,
|
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,
|
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61,
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61,
|
0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61,
|
||||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x05,
|
0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c,
|
||||||
0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72,
|
0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72,
|
||||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32,
|
0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64,
|
||||||
0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
|
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x42, 0x0c,
|
||||||
0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65,
|
0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a,
|
||||||
0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20,
|
0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x08,
|
||||||
0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a,
|
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08,
|
||||||
0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x73, 0x0a, 0x19, 0x4e,
|
0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||||
0x50, 0x4d, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00,
|
||||||
0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e,
|
0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0c, 0x61,
|
||||||
0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48,
|
0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
||||||
0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73,
|
||||||
0x22, 0x74, 0x0a, 0x1a, 0x50, 0x79, 0x50, 0x49, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
|
||||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48,
|
0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
0x61, 0x6c, 0x22, 0x94, 0x01, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12, 0x1a, 0x0a,
|
||||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x73,
|
||||||
0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65,
|
0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
0x52, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xfd, 0x01, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x37, 0x0a,
|
0x18, 0x0a, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x52, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6c, 0x73,
|
||||||
0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e,
|
0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65,
|
||||||
0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x61, 0x63, 0x63,
|
0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68,
|
0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x50, 0x75,
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
|
||||||
0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e,
|
0x69, 0x6e, 0x67, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||||
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52,
|
0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63,
|
||||||
0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
|
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74,
|
||||||
0x12, 0x4c, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f,
|
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e,
|
||||||
0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72,
|
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a,
|
||||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45,
|
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64,
|
||||||
0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6c,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70,
|
||||||
0x6f, 0x75, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18,
|
0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, 0x65, 0x70,
|
||||||
0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x74, 0x68, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a, 0x05, 0x53, 0x6c, 0x61, 0x63, 0x6b,
|
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73,
|
||||||
0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
0x69, 0x6e, 0x63, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||||
0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e,
|
0x61, 0x6c, 0x22, 0x51, 0x0a, 0x0d, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x6c, 0x74,
|
||||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x32,
|
0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||||
0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18,
|
0x73, 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52,
|
||||||
0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x6c, 0x61,
|
0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||||
0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, 0x6b, 0x65,
|
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2a, 0xb7, 0x06, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||||
0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x03,
|
0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e,
|
0x59, 0x50, 0x45, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47,
|
||||||
0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03,
|
0x45, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59,
|
||||||
0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x0c,
|
0x50, 0x45, 0x5f, 0x42, 0x49, 0x54, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, 0x12, 0x18,
|
||||||
0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x06, 0x0a, 0x04,
|
0x0a, 0x14, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x49,
|
||||||
0x54, 0x65, 0x73, 0x74, 0x22, 0x31, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74,
|
0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52,
|
||||||
0x65, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x4c, 0x55, 0x45, 0x4e,
|
||||||
0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65,
|
0x43, 0x45, 0x10, 0x03, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54,
|
||||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xdb, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x72, 0x72,
|
0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x4b, 0x45, 0x52, 0x48, 0x55, 0x42, 0x5f, 0x49, 0x4d,
|
||||||
0x69, 0x74, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01,
|
0x41, 0x47, 0x45, 0x53, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08,
|
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x43, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53,
|
||||||
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69,
|
0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x10, 0x06,
|
||||||
0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63,
|
0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63,
|
0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52,
|
||||||
0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74,
|
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x47,
|
||||||
0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
0x49, 0x54, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54,
|
||||||
0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65,
|
0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10,
|
||||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65,
|
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x49, 0x52, 0x41,
|
||||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75,
|
0x10, 0x0a, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50,
|
||||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70,
|
0x45, 0x5f, 0x4e, 0x50, 0x4d, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, 0x41,
|
||||||
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70,
|
0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4f, 0x55, 0x52,
|
||||||
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65,
|
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x59, 0x50, 0x49, 0x5f, 0x55, 0x4e, 0x41,
|
||||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xa5, 0x01, 0x0a, 0x07, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e,
|
0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0c, 0x12,
|
||||||
0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20,
|
0x12, 0x0a, 0x0e, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
|
||||||
0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65,
|
0x33, 0x10, 0x0d, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59,
|
||||||
0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63,
|
0x50, 0x45, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x0e, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f,
|
||||||
0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72,
|
0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x59,
|
||||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41,
|
0x53, 0x54, 0x45, 0x4d, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
|
||||||
0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68,
|
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x10, 0x12, 0x14, 0x0a, 0x10, 0x53,
|
||||||
0x12, 0x2d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10,
|
||||||
0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x48,
|
0x11, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||||
0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42,
|
0x5f, 0x53, 0x33, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44, 0x10, 0x12, 0x12, 0x2a,
|
||||||
0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xf0, 0x01,
|
0x0a, 0x26, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49,
|
||||||
0x0a, 0x05, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
|
0x54, 0x48, 0x55, 0x42, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43,
|
||||||
0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03,
|
0x41, 0x54, 0x45, 0x44, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x13, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f,
|
||||||
0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a,
|
0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x4b,
|
||||||
0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05,
|
0x49, 0x54, 0x45, 0x10, 0x14, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f,
|
||||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x46, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x52, 0x52, 0x49, 0x54, 0x10, 0x15, 0x12, 0x17, 0x0a,
|
||||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63,
|
0x13, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x45, 0x4e,
|
||||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
|
0x4b, 0x49, 0x4e, 0x53, 0x10, 0x16, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
|
||||||
0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0d,
|
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x17, 0x12, 0x21, 0x0a,
|
||||||
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a,
|
0x1d, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x46, 0x52,
|
||||||
0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x4f, 0x47, 0x5f, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x18,
|
||||||
0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e,
|
0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||||
0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69,
|
0x53, 0x59, 0x53, 0x4c, 0x4f, 0x47, 0x10, 0x19, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x4f, 0x55, 0x52,
|
||||||
0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61,
|
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x45,
|
||||||
0x6d, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d,
|
0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x49, 0x4e, 0x47, 0x10,
|
||||||
0x49, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
0x1a, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||||
0x22, 0xc3, 0x01, 0x0a, 0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79,
|
0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x54, 0x49, 0x4d, 0x45, 0x10,
|
||||||
0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
0x1b, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||||
0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e,
|
0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x44, 0x52, 0x49, 0x56, 0x45, 0x10, 0x1c, 0x42,
|
||||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f,
|
0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72,
|
||||||
0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65,
|
0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72,
|
||||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75,
|
0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
|
||||||
0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12,
|
0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
0x23, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54,
|
|
||||||
0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
|
|
||||||
0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f,
|
|
||||||
0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x94, 0x01, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x6c, 0x6f,
|
|
||||||
0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x24, 0x0a,
|
|
||||||
0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72,
|
|
||||||
0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x18, 0x03,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x12, 0x16, 0x0a,
|
|
||||||
0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74,
|
|
||||||
0x6c, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18,
|
|
||||||
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xd6, 0x01,
|
|
||||||
0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e,
|
|
||||||
0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74,
|
|
||||||
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
|
||||||
0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55,
|
|
||||||
0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00,
|
|
||||||
0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
|
|
||||||
0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78,
|
|
||||||
0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61,
|
|
||||||
0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18,
|
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
|
||||||
0x70, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64,
|
|
||||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x51, 0x0a, 0x0d, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x52,
|
|
||||||
0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
|
|
||||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
|
||||||
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
|
||||||
0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63,
|
|
||||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2a, 0xd5, 0x06, 0x0a, 0x0a, 0x53, 0x6f,
|
|
||||||
0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x4f, 0x55, 0x52,
|
|
||||||
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x53, 0x54,
|
|
||||||
0x4f, 0x52, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f, 0x55, 0x52, 0x43,
|
|
||||||
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x49, 0x54, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54,
|
|
||||||
0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50,
|
|
||||||
0x45, 0x5f, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16,
|
|
||||||
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46,
|
|
||||||
0x4c, 0x55, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x4f, 0x55, 0x52,
|
|
||||||
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x4b, 0x45, 0x52, 0x48, 0x55,
|
|
||||||
0x42, 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f,
|
|
||||||
0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x43, 0x52, 0x10, 0x05, 0x12,
|
|
||||||
0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47,
|
|
||||||
0x43, 0x53, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54,
|
|
||||||
0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16,
|
|
||||||
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c,
|
|
||||||
0x49, 0x43, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52,
|
|
||||||
0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x09,
|
|
||||||
0x12, 0x14, 0x0a, 0x10, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
|
||||||
0x4a, 0x49, 0x52, 0x41, 0x10, 0x0a, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
|
|
||||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x50, 0x4d, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48,
|
|
||||||
0x44, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x25, 0x0a, 0x21,
|
|
||||||
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x59, 0x50, 0x49,
|
|
||||||
0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45,
|
|
||||||
0x53, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59,
|
|
||||||
0x50, 0x45, 0x5f, 0x53, 0x33, 0x10, 0x0d, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43,
|
|
||||||
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x0e, 0x12, 0x1a,
|
|
||||||
0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49,
|
|
||||||
0x4c, 0x45, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f,
|
|
||||||
0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x10, 0x12,
|
|
||||||
0x14, 0x0a, 0x10, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54,
|
|
||||||
0x45, 0x53, 0x54, 0x10, 0x11, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f,
|
|
||||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x33, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44,
|
|
||||||
0x10, 0x12, 0x12, 0x2a, 0x0a, 0x26, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50,
|
|
||||||
0x45, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45,
|
|
||||||
0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x13, 0x12, 0x19,
|
|
||||||
0x0a, 0x15, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55,
|
|
||||||
0x49, 0x4c, 0x44, 0x4b, 0x49, 0x54, 0x45, 0x10, 0x14, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55,
|
|
||||||
0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x52, 0x52, 0x49, 0x54, 0x10,
|
|
||||||
0x15, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
|
||||||
0x5f, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x10, 0x16, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f,
|
|
||||||
0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10,
|
|
||||||
0x17, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
|
||||||
0x5f, 0x4a, 0x46, 0x52, 0x4f, 0x47, 0x5f, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x4f,
|
|
||||||
0x52, 0x59, 0x10, 0x18, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54,
|
|
||||||
0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x4c, 0x4f, 0x47, 0x10, 0x19, 0x12, 0x27, 0x0a, 0x23,
|
|
||||||
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c,
|
|
||||||
0x49, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52,
|
|
||||||
0x49, 0x4e, 0x47, 0x10, 0x1a, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f,
|
|
||||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x54,
|
|
||||||
0x49, 0x4d, 0x45, 0x10, 0x1b, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f,
|
|
||||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x44, 0x52, 0x49, 0x56,
|
|
||||||
0x45, 0x10, 0x1c, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59,
|
|
||||||
0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44, 0x10,
|
|
||||||
0x1e, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
|
||||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f,
|
|
||||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b,
|
|
||||||
0x67, 0x2f, 0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x70, 0x62, 0x62, 0x06,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -3262,9 +3117,9 @@ var file_sources_proto_goTypes = []interface{}{
|
|||||||
(*credentialspb.Unauthenticated)(nil), // 32: credentials.Unauthenticated
|
(*credentialspb.Unauthenticated)(nil), // 32: credentials.Unauthenticated
|
||||||
(*credentialspb.Oauth2)(nil), // 33: credentials.Oauth2
|
(*credentialspb.Oauth2)(nil), // 33: credentials.Oauth2
|
||||||
(*credentialspb.KeySecret)(nil), // 34: credentials.KeySecret
|
(*credentialspb.KeySecret)(nil), // 34: credentials.KeySecret
|
||||||
(*credentialspb.CloudEnvironment)(nil), // 35: credentials.CloudEnvironment
|
(*credentialspb.SSHAuth)(nil), // 35: credentials.SSHAuth
|
||||||
(*credentialspb.SSHAuth)(nil), // 36: credentials.SSHAuth
|
(*credentialspb.GitHubApp)(nil), // 36: credentials.GitHubApp
|
||||||
(*credentialspb.GitHubApp)(nil), // 37: credentials.GitHubApp
|
(*credentialspb.CloudEnvironment)(nil), // 37: credentials.CloudEnvironment
|
||||||
(*credentialspb.SlackTokens)(nil), // 38: credentials.SlackTokens
|
(*credentialspb.SlackTokens)(nil), // 38: credentials.SlackTokens
|
||||||
(*credentialspb.Header)(nil), // 39: credentials.Header
|
(*credentialspb.Header)(nil), // 39: credentials.Header
|
||||||
(*credentialspb.ClientCredentials)(nil), // 40: credentials.ClientCredentials
|
(*credentialspb.ClientCredentials)(nil), // 40: credentials.ClientCredentials
|
||||||
@@ -3282,39 +3137,36 @@ var file_sources_proto_depIdxs = []int32{
|
|||||||
1, // 8: sources.Confluence.spaces_scope:type_name -> sources.Confluence.GetAllSpacesScope
|
1, // 8: sources.Confluence.spaces_scope:type_name -> sources.Confluence.GetAllSpacesScope
|
||||||
32, // 9: sources.DockerHub.unauthenticated:type_name -> credentials.Unauthenticated
|
32, // 9: sources.DockerHub.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
34, // 10: sources.ECR.access_key:type_name -> credentials.KeySecret
|
34, // 10: sources.ECR.access_key:type_name -> credentials.KeySecret
|
||||||
32, // 11: sources.GCS.unauthenticated:type_name -> credentials.Unauthenticated
|
31, // 11: sources.Git.basic_auth:type_name -> credentials.BasicAuth
|
||||||
35, // 12: sources.GCS.adc:type_name -> credentials.CloudEnvironment
|
32, // 12: sources.Git.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
33, // 13: sources.GCS.oauth:type_name -> credentials.Oauth2
|
35, // 13: sources.Git.ssh_auth:type_name -> credentials.SSHAuth
|
||||||
31, // 14: sources.Git.basic_auth:type_name -> credentials.BasicAuth
|
33, // 14: sources.GitLab.oauth:type_name -> credentials.Oauth2
|
||||||
32, // 15: sources.Git.unauthenticated:type_name -> credentials.Unauthenticated
|
31, // 15: sources.GitLab.basic_auth:type_name -> credentials.BasicAuth
|
||||||
36, // 16: sources.Git.ssh_auth:type_name -> credentials.SSHAuth
|
36, // 16: sources.GitHub.github_app:type_name -> credentials.GitHubApp
|
||||||
33, // 17: sources.GitLab.oauth:type_name -> credentials.Oauth2
|
32, // 17: sources.GitHub.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
31, // 18: sources.GitLab.basic_auth:type_name -> credentials.BasicAuth
|
31, // 18: sources.JIRA.basic_auth:type_name -> credentials.BasicAuth
|
||||||
37, // 19: sources.GitHub.github_app:type_name -> credentials.GitHubApp
|
32, // 19: sources.JIRA.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
32, // 20: sources.GitHub.unauthenticated:type_name -> credentials.Unauthenticated
|
33, // 20: sources.JIRA.oauth:type_name -> credentials.Oauth2
|
||||||
31, // 21: sources.JIRA.basic_auth:type_name -> credentials.BasicAuth
|
32, // 21: sources.NPMUnauthenticatedPackage.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
32, // 22: sources.JIRA.unauthenticated:type_name -> credentials.Unauthenticated
|
32, // 22: sources.PyPIUnauthenticatedPackage.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
33, // 23: sources.JIRA.oauth:type_name -> credentials.Oauth2
|
34, // 23: sources.S3.access_key:type_name -> credentials.KeySecret
|
||||||
32, // 24: sources.NPMUnauthenticatedPackage.unauthenticated:type_name -> credentials.Unauthenticated
|
32, // 24: sources.S3.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
32, // 25: sources.PyPIUnauthenticatedPackage.unauthenticated:type_name -> credentials.Unauthenticated
|
37, // 25: sources.S3.cloud_environment:type_name -> credentials.CloudEnvironment
|
||||||
34, // 26: sources.S3.access_key:type_name -> credentials.KeySecret
|
38, // 26: sources.Slack.tokens:type_name -> credentials.SlackTokens
|
||||||
32, // 27: sources.S3.unauthenticated:type_name -> credentials.Unauthenticated
|
31, // 27: sources.Gerrit.basic_auth:type_name -> credentials.BasicAuth
|
||||||
35, // 28: sources.S3.cloud_environment:type_name -> credentials.CloudEnvironment
|
32, // 28: sources.Gerrit.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
38, // 29: sources.Slack.tokens:type_name -> credentials.SlackTokens
|
31, // 29: sources.Jenkins.basic_auth:type_name -> credentials.BasicAuth
|
||||||
31, // 30: sources.Gerrit.basic_auth:type_name -> credentials.BasicAuth
|
39, // 30: sources.Jenkins.header:type_name -> credentials.Header
|
||||||
32, // 31: sources.Gerrit.unauthenticated:type_name -> credentials.Unauthenticated
|
40, // 31: sources.Teams.authenticated:type_name -> credentials.ClientCredentials
|
||||||
31, // 32: sources.Jenkins.basic_auth:type_name -> credentials.BasicAuth
|
31, // 32: sources.Artifactory.basic_auth:type_name -> credentials.BasicAuth
|
||||||
39, // 33: sources.Jenkins.header:type_name -> credentials.Header
|
32, // 33: sources.PublicEventMonitoring.unauthenticated:type_name -> credentials.Unauthenticated
|
||||||
40, // 34: sources.Teams.authenticated:type_name -> credentials.ClientCredentials
|
41, // 34: sources.PublicEventMonitoring.since:type_name -> google.protobuf.Timestamp
|
||||||
31, // 35: sources.Artifactory.basic_auth:type_name -> credentials.BasicAuth
|
38, // 35: sources.SlackRealtime.tokens:type_name -> credentials.SlackTokens
|
||||||
32, // 36: sources.PublicEventMonitoring.unauthenticated:type_name -> credentials.Unauthenticated
|
36, // [36:36] is the sub-list for method output_type
|
||||||
41, // 37: sources.PublicEventMonitoring.since:type_name -> google.protobuf.Timestamp
|
36, // [36:36] is the sub-list for method input_type
|
||||||
38, // 38: sources.SlackRealtime.tokens:type_name -> credentials.SlackTokens
|
36, // [36:36] is the sub-list for extension type_name
|
||||||
39, // [39:39] is the sub-list for method output_type
|
36, // [36:36] is the sub-list for extension extendee
|
||||||
39, // [39:39] is the sub-list for method input_type
|
0, // [0:36] is the sub-list for field type_name
|
||||||
39, // [39:39] is the sub-list for extension type_name
|
|
||||||
39, // [39:39] is the sub-list for extension extendee
|
|
||||||
0, // [0:39] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_sources_proto_init() }
|
func init() { file_sources_proto_init() }
|
||||||
@@ -3674,12 +3526,7 @@ func file_sources_proto_init() {
|
|||||||
(*ECR_AccessKey)(nil),
|
(*ECR_AccessKey)(nil),
|
||||||
}
|
}
|
||||||
file_sources_proto_msgTypes[8].OneofWrappers = []interface{}{
|
file_sources_proto_msgTypes[8].OneofWrappers = []interface{}{
|
||||||
(*GCS_JsonServiceAccount)(nil),
|
(*GCS_JsonSa)(nil),
|
||||||
(*GCS_ApiKey)(nil),
|
|
||||||
(*GCS_Unauthenticated)(nil),
|
|
||||||
(*GCS_Adc)(nil),
|
|
||||||
(*GCS_ServiceAccountFile)(nil),
|
|
||||||
(*GCS_Oauth)(nil),
|
|
||||||
}
|
}
|
||||||
file_sources_proto_msgTypes[9].OneofWrappers = []interface{}{
|
file_sources_proto_msgTypes[9].OneofWrappers = []interface{}{
|
||||||
(*Git_BasicAuth)(nil),
|
(*Git_BasicAuth)(nil),
|
||||||
|
|||||||
@@ -1242,113 +1242,10 @@ func (m *GCS) validate(all bool) error {
|
|||||||
|
|
||||||
var errors []error
|
var errors []error
|
||||||
|
|
||||||
// no validation rules for ProjectId
|
|
||||||
|
|
||||||
// no validation rules for MaxObjectSize
|
|
||||||
|
|
||||||
switch m.Credential.(type) {
|
switch m.Credential.(type) {
|
||||||
|
|
||||||
case *GCS_JsonServiceAccount:
|
case *GCS_JsonSa:
|
||||||
// no validation rules for JsonServiceAccount
|
// no validation rules for JsonSa
|
||||||
|
|
||||||
case *GCS_ApiKey:
|
|
||||||
// no validation rules for ApiKey
|
|
||||||
|
|
||||||
case *GCS_Unauthenticated:
|
|
||||||
|
|
||||||
if all {
|
|
||||||
switch v := interface{}(m.GetUnauthenticated()).(type) {
|
|
||||||
case interface{ ValidateAll() error }:
|
|
||||||
if err := v.ValidateAll(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Unauthenticated",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
case interface{ Validate() error }:
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Unauthenticated",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if v, ok := interface{}(m.GetUnauthenticated()).(interface{ Validate() error }); ok {
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
return GCSValidationError{
|
|
||||||
field: "Unauthenticated",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *GCS_Adc:
|
|
||||||
|
|
||||||
if all {
|
|
||||||
switch v := interface{}(m.GetAdc()).(type) {
|
|
||||||
case interface{ ValidateAll() error }:
|
|
||||||
if err := v.ValidateAll(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Adc",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
case interface{ Validate() error }:
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Adc",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if v, ok := interface{}(m.GetAdc()).(interface{ Validate() error }); ok {
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
return GCSValidationError{
|
|
||||||
field: "Adc",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *GCS_ServiceAccountFile:
|
|
||||||
// no validation rules for ServiceAccountFile
|
|
||||||
|
|
||||||
case *GCS_Oauth:
|
|
||||||
|
|
||||||
if all {
|
|
||||||
switch v := interface{}(m.GetOauth()).(type) {
|
|
||||||
case interface{ ValidateAll() error }:
|
|
||||||
if err := v.ValidateAll(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Oauth",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
case interface{ Validate() error }:
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
errors = append(errors, GCSValidationError{
|
|
||||||
field: "Oauth",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if v, ok := interface{}(m.GetOauth()).(interface{ Validate() error }); ok {
|
|
||||||
if err := v.Validate(); err != nil {
|
|
||||||
return GCSValidationError{
|
|
||||||
field: "Oauth",
|
|
||||||
reason: "embedded message failed validation",
|
|
||||||
cause: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,265 +0,0 @@
|
|||||||
package gcs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
diskbufferreader "github.com/bill-rich/disk-buffer-reader"
|
|
||||||
"github.com/go-errors/errors"
|
|
||||||
"github.com/go-logr/logr"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"google.golang.org/protobuf/types/known/anypb"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/handlers"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ensure the Source satisfies the interface at compile time.
|
|
||||||
var _ sources.Source = (*Source)(nil)
|
|
||||||
|
|
||||||
// Type returns the type of source.
|
|
||||||
// It is used for matching source types in configuration and job input.
|
|
||||||
func (s *Source) Type() sourcespb.SourceType {
|
|
||||||
return sourcespb.SourceType_SOURCE_TYPE_GCS
|
|
||||||
}
|
|
||||||
|
|
||||||
// SourceID number for GCS Source.
|
|
||||||
func (s *Source) SourceID() int64 {
|
|
||||||
return s.sourceId
|
|
||||||
}
|
|
||||||
|
|
||||||
// JobID number for GCS Source.
|
|
||||||
func (s *Source) JobID() int64 {
|
|
||||||
return s.jobId
|
|
||||||
}
|
|
||||||
|
|
||||||
// Source represents a GCS source.
|
|
||||||
type Source struct {
|
|
||||||
name string
|
|
||||||
jobId int64
|
|
||||||
sourceId int64
|
|
||||||
concurrency int
|
|
||||||
verify bool
|
|
||||||
|
|
||||||
gcsManager objectManager
|
|
||||||
stats *attributes
|
|
||||||
log logr.Logger
|
|
||||||
chunksCh chan *sources.Chunk
|
|
||||||
|
|
||||||
sources.Progress
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init returns an initialized GCS source.
|
|
||||||
func (s *Source) Init(aCtx context.Context, name string, id int64, sourceID int64, verify bool, connection *anypb.Any, concurrency int) error {
|
|
||||||
s.log = aCtx.Logger()
|
|
||||||
|
|
||||||
s.name = name
|
|
||||||
s.verify = verify
|
|
||||||
s.sourceId = sourceID
|
|
||||||
s.jobId = id
|
|
||||||
s.concurrency = concurrency
|
|
||||||
|
|
||||||
var conn sourcespb.GCS
|
|
||||||
err := anypb.UnmarshalTo(connection, &conn, proto.UnmarshalOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return errors.WrapPrefix(err, "error unmarshalling connection", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
gcsManager, err := configureGCSManager(aCtx, &conn, concurrency)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.gcsManager = gcsManager
|
|
||||||
|
|
||||||
s.log.V(2).Info("enumerating buckets and objects")
|
|
||||||
if err := s.enumerate(aCtx); err != nil {
|
|
||||||
return fmt.Errorf("error enumerating buckets and objects: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func configureGCSManager(aCtx context.Context, conn *sourcespb.GCS, concurrency int) (*gcsManager, error) {
|
|
||||||
if conn == nil {
|
|
||||||
return nil, fmt.Errorf("GCS connection is nil, cannot configure GCS manager")
|
|
||||||
}
|
|
||||||
|
|
||||||
var gcsManagerAuthOption gcsManagerOption
|
|
||||||
|
|
||||||
switch conn.Credential.(type) {
|
|
||||||
case *sourcespb.GCS_ApiKey:
|
|
||||||
gcsManagerAuthOption = withAPIKey(aCtx, conn.GetApiKey())
|
|
||||||
case *sourcespb.GCS_ServiceAccountFile:
|
|
||||||
b, err := os.ReadFile(conn.GetServiceAccountFile())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading GCS JSON Service Account file: %w", err)
|
|
||||||
}
|
|
||||||
gcsManagerAuthOption = withJSONServiceAccount(aCtx, b)
|
|
||||||
case *sourcespb.GCS_JsonServiceAccount:
|
|
||||||
gcsManagerAuthOption = withJSONServiceAccount(aCtx, []byte(conn.GetJsonServiceAccount()))
|
|
||||||
case *sourcespb.GCS_Adc:
|
|
||||||
gcsManagerAuthOption = withDefaultADC(aCtx)
|
|
||||||
case *sourcespb.GCS_Unauthenticated:
|
|
||||||
gcsManagerAuthOption = withoutAuthentication()
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown GCS authentication type: %T", conn.Credential)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
gcsManagerOpts := []gcsManagerOption{
|
|
||||||
withConcurrency(concurrency),
|
|
||||||
withMaxObjectSize(conn.MaxObjectSize),
|
|
||||||
gcsManagerAuthOption,
|
|
||||||
}
|
|
||||||
if setGCSManagerBucketOptions(conn) != nil {
|
|
||||||
gcsManagerOpts = append(gcsManagerOpts, setGCSManagerBucketOptions(conn))
|
|
||||||
}
|
|
||||||
if setGCSManagerObjectOptions(conn) != nil {
|
|
||||||
gcsManagerOpts = append(gcsManagerOpts, setGCSManagerObjectOptions(conn))
|
|
||||||
}
|
|
||||||
|
|
||||||
gcsManager, err := newGCSManager(conn.ProjectId, gcsManagerOpts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error creating GCS manager: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gcsManager, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setGCSManagerBucketOptions(conn *sourcespb.GCS) gcsManagerOption {
|
|
||||||
return setGCSManagerOptions(conn.GetIncludeBuckets(), conn.GetExcludeBuckets(), withIncludeBuckets, withExcludeBuckets)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setGCSManagerObjectOptions(conn *sourcespb.GCS) gcsManagerOption {
|
|
||||||
return setGCSManagerOptions(conn.GetIncludeObjects(), conn.GetExcludeObjects(), withIncludeObjects, withExcludeObjects)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setGCSManagerOptions(include, exclude []string, includeFn, excludeFn func([]string) gcsManagerOption) gcsManagerOption {
|
|
||||||
// Only allow one of include/exclude to be set.
|
|
||||||
// If both are set, include takes precedence.
|
|
||||||
if len(include) > 0 {
|
|
||||||
return includeFn(include)
|
|
||||||
}
|
|
||||||
if len(exclude) > 0 {
|
|
||||||
return excludeFn(exclude)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// enumerate all the objects and buckets in the source.
|
|
||||||
func (s *Source) enumerate(ctx context.Context) error {
|
|
||||||
stats, err := s.gcsManager.attributes(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting attributes during enumeration: %w", err)
|
|
||||||
}
|
|
||||||
s.stats = stats
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chunks emits chunks of bytes over a channel.
|
|
||||||
func (s *Source) Chunks(ctx context.Context, chunksChan chan *sources.Chunk) error {
|
|
||||||
objectCh, err := s.gcsManager.listObjects(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error listing objects: %w", err)
|
|
||||||
}
|
|
||||||
s.chunksCh = chunksChan
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for obj := range objectCh {
|
|
||||||
obj := obj
|
|
||||||
o, ok := obj.(object)
|
|
||||||
if !ok {
|
|
||||||
ctx.Logger().Error(fmt.Errorf("unexpected object type: %T", obj), "GCS source unexpected object type", "name", s.name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Add(1)
|
|
||||||
go func(obj object) {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
if err := s.processObject(ctx, o); err != nil {
|
|
||||||
ctx.Logger().V(1).Info("error setting start progress progress", "name", o.name, "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(o)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) processObject(ctx context.Context, o object) error {
|
|
||||||
chunkSkel := &sources.Chunk{
|
|
||||||
SourceName: s.name,
|
|
||||||
SourceType: s.Type(),
|
|
||||||
SourceID: s.sourceId,
|
|
||||||
Verify: s.verify,
|
|
||||||
SourceMetadata: &source_metadatapb.MetaData{
|
|
||||||
Data: &source_metadatapb.MetaData_Gcs{
|
|
||||||
Gcs: &source_metadatapb.GCS{
|
|
||||||
Bucket: o.bucket,
|
|
||||||
Filename: o.name,
|
|
||||||
Link: o.link,
|
|
||||||
Email: o.owner,
|
|
||||||
ContentType: o.contentType,
|
|
||||||
Acls: o.acl,
|
|
||||||
CreatedAt: strconv.FormatInt(o.createdAt.Unix(), 10), // Unix time as string
|
|
||||||
UpdatedAt: o.updatedAt.String(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := s.readObjectData(ctx, o, chunkSkel)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error reading object data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If data is nil, it means that the file was handled by a handler.
|
|
||||||
if data == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
chunkSkel.Data = data
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
case s.chunksCh <- chunkSkel:
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) readObjectData(ctx context.Context, o object, chunk *sources.Chunk) ([]byte, error) {
|
|
||||||
reader, err := diskbufferreader.New(o)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error creating disk buffer reader: %w", err)
|
|
||||||
}
|
|
||||||
defer reader.Close()
|
|
||||||
|
|
||||||
if handlers.HandleFile(ctx, reader, chunk, s.chunksCh) {
|
|
||||||
ctx.Logger().V(3).Info("File was handled", "name", s.name, "bucket", o.bucket, "object", o.name)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := reader.Reset(); err != nil {
|
|
||||||
return nil, fmt.Errorf("error resetting reader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.Stop()
|
|
||||||
data, err := io.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading object: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
//go:build integration
|
|
||||||
// +build integration
|
|
||||||
|
|
||||||
package gcs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestChunks(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
source, conn := createTestSource(&sourcespb.GCS{
|
|
||||||
ProjectId: testProjectID,
|
|
||||||
Credential: &sourcespb.GCS_Adc{},
|
|
||||||
ExcludeBuckets: []string{perfTestBucketGlob, publicBucket},
|
|
||||||
})
|
|
||||||
|
|
||||||
err := source.Init(ctx, "test", 1, 1, true, conn, 8)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
chunksCh := make(chan *sources.Chunk, 1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer close(chunksCh)
|
|
||||||
err := source.Chunks(ctx, chunksCh)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
want := createTestChunks()
|
|
||||||
|
|
||||||
got := make([]*sources.Chunk, 0, len(want))
|
|
||||||
for chunk := range chunksCh {
|
|
||||||
got = append(got, chunk)
|
|
||||||
}
|
|
||||||
sort.Slice(got, func(i, j int) bool {
|
|
||||||
return got[i].SourceMetadata.GetGcs().Filename < got[j].SourceMetadata.GetGcs().Filename
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Equal(t, len(want), len(got))
|
|
||||||
|
|
||||||
for i, chunk := range got {
|
|
||||||
if diff := cmp.Diff(want[i].SourceMetadata.GetGcs(), chunk.SourceMetadata.GetGcs(),
|
|
||||||
cmpopts.IgnoreFields(source_metadatapb.GCS{}, "state", "sizeCache", "unknownFields", "CreatedAt", "UpdatedAt"),
|
|
||||||
); diff != "" {
|
|
||||||
t.Errorf("chunk mismatch (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChunks_PublicBucket(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
source, conn := createTestSource(&sourcespb.GCS{
|
|
||||||
Credential: &sourcespb.GCS_Unauthenticated{},
|
|
||||||
IncludeBuckets: []string{publicBucket},
|
|
||||||
})
|
|
||||||
|
|
||||||
err := source.Init(ctx, "test", 1, 1, true, conn, 8)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
chunksCh := make(chan *sources.Chunk, 1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer close(chunksCh)
|
|
||||||
err := source.Chunks(ctx, chunksCh)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
want := []*sources.Chunk{
|
|
||||||
{
|
|
||||||
SourceName: "test",
|
|
||||||
SourceType: sourcespb.SourceType_SOURCE_TYPE_GCS,
|
|
||||||
SourceID: 0,
|
|
||||||
Verify: true,
|
|
||||||
SourceMetadata: &source_metadatapb.MetaData{
|
|
||||||
Data: &source_metadatapb.MetaData_Gcs{
|
|
||||||
Gcs: &source_metadatapb.GCS{
|
|
||||||
Filename: "aws1.txt",
|
|
||||||
Bucket: publicBucket,
|
|
||||||
ContentType: "text/plain",
|
|
||||||
Email: "",
|
|
||||||
Link: "https://storage.googleapis.com/download/storage/v1/b/public-trufflehog-test-bucket/o/aws1.txt?generation=1678334408999764&alt=media",
|
|
||||||
Acls: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
got := make([]*sources.Chunk, 0, len(want))
|
|
||||||
for chunk := range chunksCh {
|
|
||||||
got = append(got, chunk)
|
|
||||||
}
|
|
||||||
sort.Slice(got, func(i, j int) bool {
|
|
||||||
return got[i].SourceMetadata.GetGcs().Filename < got[j].SourceMetadata.GetGcs().Filename
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Equal(t, len(want), len(got))
|
|
||||||
|
|
||||||
for i, chunk := range got {
|
|
||||||
if diff := cmp.Diff(want[i].SourceMetadata.GetGcs(), chunk.SourceMetadata.GetGcs(),
|
|
||||||
cmpopts.IgnoreFields(source_metadatapb.GCS{}, "state", "sizeCache", "unknownFields", "CreatedAt", "UpdatedAt"),
|
|
||||||
); diff != "" {
|
|
||||||
t.Errorf("chunk mismatch (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestChunks() []*sources.Chunk {
|
|
||||||
objects := []object{
|
|
||||||
{
|
|
||||||
name: "aws1.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/aws1.txt?generation=1677870994890594&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar2.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 12,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/moar2.txt?generation=1677871000378542&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "aws3.txt",
|
|
||||||
bucket: testBucket2,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th2/o/aws3.txt?generation=1677871022489611&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar.txt",
|
|
||||||
bucket: testBucket3,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 6,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th3/o/moar.txt?generation=1677871042896804&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "AMAZON_FASHION_5.json",
|
|
||||||
bucket: testBucket4,
|
|
||||||
contentType: "application/json",
|
|
||||||
size: 1413469,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th4/o/AMAZON_FASHION_5.json?generation=1677871063457469&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
chunks := make([]*sources.Chunk, 0, len(objects))
|
|
||||||
for _, o := range objects {
|
|
||||||
chunks = append(chunks, &sources.Chunk{
|
|
||||||
SourceName: "test",
|
|
||||||
SourceType: sourcespb.SourceType_SOURCE_TYPE_GCS,
|
|
||||||
SourceID: 0,
|
|
||||||
Verify: true,
|
|
||||||
SourceMetadata: &source_metadatapb.MetaData{
|
|
||||||
Data: &source_metadatapb.MetaData_Gcs{
|
|
||||||
Gcs: &source_metadatapb.GCS{
|
|
||||||
Filename: o.name,
|
|
||||||
Bucket: o.bucket,
|
|
||||||
ContentType: o.contentType,
|
|
||||||
Email: o.owner,
|
|
||||||
Link: o.link,
|
|
||||||
Acls: o.acl,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Slice(chunks, func(i, j int) bool {
|
|
||||||
return chunks[i].SourceMetadata.GetGcs().Filename < chunks[j].SourceMetadata.GetGcs().Filename
|
|
||||||
})
|
|
||||||
|
|
||||||
return chunks
|
|
||||||
}
|
|
||||||
@@ -1,719 +0,0 @@
|
|||||||
package gcs
|
|
||||||
|
|
||||||
import (
|
|
||||||
aCtx "context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
|
||||||
"github.com/gobwas/glob"
|
|
||||||
"github.com/googleapis/gax-go/v2"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
"google.golang.org/api/iterator"
|
|
||||||
"google.golang.org/api/option"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultMaxObjectSize = 10 * 1024 * 1024 // 10MB
|
|
||||||
maxObjectSizeLimit = 50 * 1024 * 1024 // 50MB
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultConcurrency = runtime.NumCPU()
|
|
||||||
)
|
|
||||||
|
|
||||||
type objectManager interface {
|
|
||||||
listObjects(context.Context) (chan io.Reader, error)
|
|
||||||
attributes(ctx context.Context) (*attributes, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// bucketManager is a simplified *storage.Client wrapper.
|
|
||||||
// It provides only a subset of methods that are needed by the gcsManager.
|
|
||||||
type bucketManager interface {
|
|
||||||
// Bucket returns a BucketHandle for the given bucket name.
|
|
||||||
Bucket(name string) *storage.BucketHandle
|
|
||||||
// Buckets returns an iterator over the buckets in the project.
|
|
||||||
Buckets(ctx aCtx.Context, projectID string) *storage.BucketIterator
|
|
||||||
}
|
|
||||||
|
|
||||||
// gcsManager serves as simple facade for interacting with GCS.
|
|
||||||
// It's main purpose is to retrieve objects from GCS.
|
|
||||||
type gcsManager struct {
|
|
||||||
projectID string
|
|
||||||
withoutAuth,
|
|
||||||
hasEnumerated bool
|
|
||||||
|
|
||||||
concurrency int
|
|
||||||
workerPool *errgroup.Group
|
|
||||||
|
|
||||||
maxObjectSize int64
|
|
||||||
numBuckets uint32
|
|
||||||
numObjects uint64
|
|
||||||
|
|
||||||
includeBuckets,
|
|
||||||
excludeBuckets,
|
|
||||||
includeObjects,
|
|
||||||
excludeObjects map[string]struct{}
|
|
||||||
|
|
||||||
buckets map[string]bucket
|
|
||||||
attr *attributes
|
|
||||||
|
|
||||||
client bucketManager
|
|
||||||
}
|
|
||||||
|
|
||||||
// bucket is a simplified *storage.BucketHandle wrapper.
|
|
||||||
// It also provides a mechanism for resuming an interrupted iteration.
|
|
||||||
// This reduces the number of objects that need to be re-processed.
|
|
||||||
type bucket struct {
|
|
||||||
shouldInclude bool
|
|
||||||
name string
|
|
||||||
// startOffset is the name of the object to resume from. (inclusive)
|
|
||||||
// This works because GCS objects are sorted lexicographically.
|
|
||||||
// If this is empty, the iteration will start from the beginning.
|
|
||||||
startOffset string
|
|
||||||
*storage.BucketHandle
|
|
||||||
}
|
|
||||||
|
|
||||||
// offsetInfo is used to resume an interrupted iteration.
|
|
||||||
type offsetInfo struct {
|
|
||||||
isBucketProcessed bool
|
|
||||||
lastProcessedObject string
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes contains metadata about the GCS source.
|
|
||||||
// This will be collected during the initial scan.
|
|
||||||
type attributes struct {
|
|
||||||
numBuckets uint32
|
|
||||||
numObjects uint64
|
|
||||||
mu sync.RWMutex
|
|
||||||
bucketObjects map[string]uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func newStats(numBkts int) *attributes {
|
|
||||||
return &attributes{
|
|
||||||
numBuckets: uint32(numBkts),
|
|
||||||
bucketObjects: make(map[string]uint64, numBkts),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *attributes) incObjects() {
|
|
||||||
s.mu.Lock()
|
|
||||||
s.numObjects++
|
|
||||||
s.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *attributes) setBucketCnt(bkt string, cnt uint64) {
|
|
||||||
s.mu.Lock()
|
|
||||||
s.bucketObjects[bkt] = cnt
|
|
||||||
s.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
type gcsManagerOption func(*gcsManager) error
|
|
||||||
|
|
||||||
// withAPIKey uses the provided API key when creating a new GCS client.
|
|
||||||
// This can ONLY be used for public buckets.
|
|
||||||
func withAPIKey(ctx context.Context, apiKey string) gcsManagerOption {
|
|
||||||
client, err := storage.NewClient(ctx, option.WithAPIKey(apiKey), option.WithScopes(storage.ScopeReadOnly))
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m.client = client
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withJSONServiceAccount uses the provided JSON service account when creating a new GCS client.
|
|
||||||
func withJSONServiceAccount(ctx context.Context, jsonServiceAccount []byte) gcsManagerOption {
|
|
||||||
client, err := storage.NewClient(ctx, option.WithCredentialsJSON(jsonServiceAccount), option.WithScopes(storage.ScopeReadOnly))
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m.client = client
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withDefaultADC uses the default application credentials when creating a new GCS client.
|
|
||||||
func withDefaultADC(ctx context.Context) gcsManagerOption {
|
|
||||||
client, err := defaultADC(ctx)
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m.client = client
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withoutAuthentication uses an unauthenticated client when creating a new GCS client.
|
|
||||||
// This can ONLY be used for public buckets.
|
|
||||||
func withoutAuthentication() gcsManagerOption {
|
|
||||||
client, err := storage.NewClient(aCtx.Background(), option.WithoutAuthentication(), option.WithScopes(storage.ScopeReadOnly))
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m.client = client
|
|
||||||
m.withoutAuth = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultADC(ctx context.Context) (*storage.Client, error) {
|
|
||||||
client, err := storage.NewClient(ctx, option.WithScopes(storage.ScopeReadOnly))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return client, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// withIncludeBuckets sets the buckets that should be included in the scan.
|
|
||||||
// If used in conjunction with withExcludeBuckets, the include buckets will
|
|
||||||
// take precedence.
|
|
||||||
func withIncludeBuckets(buckets []string) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if len(buckets) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if m.excludeBuckets != nil {
|
|
||||||
m.excludeBuckets = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.includeBuckets = make(map[string]struct{}, len(buckets))
|
|
||||||
for _, bucket := range buckets {
|
|
||||||
m.includeBuckets[bucket] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withExcludeBuckets sets the buckets that should be excluded from the scan.
|
|
||||||
// If used in conjunction with withIncludeBuckets, the include buckets will
|
|
||||||
// take precedence.
|
|
||||||
func withExcludeBuckets(buckets []string) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if len(buckets) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if m.includeBuckets != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.excludeBuckets = make(map[string]struct{}, len(buckets))
|
|
||||||
for _, bucket := range buckets {
|
|
||||||
m.excludeBuckets[bucket] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withIncludeObjects sets the objects that should be included in the scan.
|
|
||||||
// Using this option in conjuection with withIncludeBuckets will result in
|
|
||||||
// only specific buckets and objects being scanned.
|
|
||||||
// If the bucket(s) are known, it is recommended to also use withIncludeBuckets
|
|
||||||
// to increase the performance of the scan.
|
|
||||||
// If used in conjunction with any of the withExclude* or withIncludeBuckets options, this
|
|
||||||
// option will take precedence.
|
|
||||||
func withIncludeObjects(objects []string) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if len(objects) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if m.excludeObjects != nil {
|
|
||||||
m.excludeObjects = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.includeObjects = make(map[string]struct{}, len(objects))
|
|
||||||
for _, object := range objects {
|
|
||||||
m.includeObjects[object] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withExcludeObjects sets the objects that should be excluded from the scan.
|
|
||||||
// If used in conjunction with withIncludeObjects, the include objects will
|
|
||||||
// take precedence.
|
|
||||||
func withExcludeObjects(objects []string) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if len(objects) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if m.includeObjects != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.excludeObjects = make(map[string]struct{}, len(objects))
|
|
||||||
for _, object := range objects {
|
|
||||||
m.excludeObjects[object] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withConcurrency sets the number of concurrent workers that will be used
|
|
||||||
// to process objects.
|
|
||||||
// If not set, or set to a negative number the default value is runtime.NumCPU().
|
|
||||||
func withConcurrency(concurrency int) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if concurrency <= 0 {
|
|
||||||
m.concurrency = defaultConcurrency
|
|
||||||
} else {
|
|
||||||
m.concurrency = concurrency
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withMaxObjectSize sets the maximum size of objects that will be scanned.
|
|
||||||
// If not set, set to a negative number, or set larger than 1GB,
|
|
||||||
// the default value of 500MB will be used.
|
|
||||||
func withMaxObjectSize(maxObjectSize int64) gcsManagerOption {
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
if maxObjectSize <= 0 || maxObjectSize > maxObjectSizeLimit {
|
|
||||||
m.maxObjectSize = defaultMaxObjectSize
|
|
||||||
} else {
|
|
||||||
m.maxObjectSize = maxObjectSize
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withBucketOffsets sets the offset for each bucket.
|
|
||||||
// This is used to resume listing objects for a bucket.
|
|
||||||
func withBucketOffsets(offsets map[string]offsetInfo) gcsManagerOption {
|
|
||||||
bkts := make(map[string]bucket, len(offsets))
|
|
||||||
for bkt, offst := range offsets {
|
|
||||||
bkts[bkt] = bucket{
|
|
||||||
shouldInclude: !offst.isBucketProcessed,
|
|
||||||
name: bkt,
|
|
||||||
startOffset: offst.lastProcessedObject,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return func(m *gcsManager) error {
|
|
||||||
m.hasEnumerated = len(offsets) > 0 // offset means we are resuming.
|
|
||||||
m.buckets = bkts
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGCSManager(projectID string, opts ...gcsManagerOption) (*gcsManager, error) {
|
|
||||||
// Default values for the manager.
|
|
||||||
gcs := &gcsManager{
|
|
||||||
projectID: projectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
buckets: make(map[string]bucket),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err := opt(gcs); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to apply option: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if projectID == "" && !gcs.withoutAuth {
|
|
||||||
return nil, fmt.Errorf("project ID is required, when using authentication")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no client was provided, use the default application credentials.
|
|
||||||
// A client is required to perform any operations.
|
|
||||||
if gcs.client == nil {
|
|
||||||
c, err := defaultADC(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gcs.client = c
|
|
||||||
}
|
|
||||||
configureWorkers(gcs)
|
|
||||||
|
|
||||||
return gcs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func configureWorkers(gcs *gcsManager) {
|
|
||||||
gcs.workerPool = new(errgroup.Group)
|
|
||||||
gcs.workerPool.SetLimit(gcs.concurrency)
|
|
||||||
}
|
|
||||||
|
|
||||||
// object is a representation of a GCS object.
|
|
||||||
type object struct {
|
|
||||||
name string
|
|
||||||
bucket string
|
|
||||||
contentType string
|
|
||||||
owner string
|
|
||||||
link string
|
|
||||||
// acl represents an ACLEntities.
|
|
||||||
// https://pkg.go.dev/cloud.google.com/go/storage#ACLEntity
|
|
||||||
acl []string
|
|
||||||
size int64
|
|
||||||
createdAt time.Time
|
|
||||||
updatedAt time.Time
|
|
||||||
|
|
||||||
io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) attributes(ctx context.Context) (*attributes, error) {
|
|
||||||
// Get all the buckets in the project.
|
|
||||||
buckets, err := g.listBuckets(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to list buckets: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return g.enumerate(ctx, buckets)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) enumerate(ctx context.Context, bkts []bucket) (*attributes, error) {
|
|
||||||
logger := ctx.Logger().WithValues("phase", "enumeration")
|
|
||||||
|
|
||||||
logger.V(5).Info("enumerating buckets", "numBuckets", len(bkts))
|
|
||||||
stats := newStats(len(bkts))
|
|
||||||
|
|
||||||
defer func(start time.Time) {
|
|
||||||
logger.V(5).Info("finished enumerating buckets", "duration-seconds", fmt.Sprintf("%.1f", time.Since(start).Seconds()), "num-buckets", len(bkts), "num-objects", stats.numObjects)
|
|
||||||
}(time.Now())
|
|
||||||
|
|
||||||
for _, bkt := range bkts {
|
|
||||||
bkt := bkt
|
|
||||||
g.workerPool.Go(func() error {
|
|
||||||
// List all the objects in the bucket and calculate a attributes.
|
|
||||||
g.setupBktHandle(&bkt)
|
|
||||||
|
|
||||||
q, err := setObjectQuery(&bkt)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(err, "failed to set object query", "bucket", bkt.name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var count uint64
|
|
||||||
objs := bkt.Objects(ctx, q)
|
|
||||||
for {
|
|
||||||
obj, err := objs.Next()
|
|
||||||
if errors.Is(err, iterator.Done) {
|
|
||||||
logger.V(5).Info("finished listing objects in bucket")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
logger.V(1).Info("failed to list objects", "bucket", bkt.name, "error", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if obj == nil {
|
|
||||||
logger.V(5).Info("object is nil")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !g.shouldIncludeObject(ctx, obj.Name) || g.shouldExcludeObject(ctx, obj.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
stats.incObjects()
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.setBucketCnt(bkt.name, count)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = g.workerPool.Wait()
|
|
||||||
g.attr = stats
|
|
||||||
|
|
||||||
return stats, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) listObjects(ctx context.Context) (chan io.Reader, error) {
|
|
||||||
ch := make(chan io.Reader, 100) // TODO (ahrav): Determine optimal buffer size.
|
|
||||||
|
|
||||||
// Get all the buckets in the project.
|
|
||||||
buckets, err := g.listBuckets(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to list buckets: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO (ahrav): This can be optimized if we set the buckets from within
|
|
||||||
// the listBuckets method. This way seems a little more clear as to the intent.
|
|
||||||
|
|
||||||
// Update the gcsManager with all the buckets to list objects from.
|
|
||||||
// This is in addition to any buckets that were provided via the
|
|
||||||
// withBucketOffsets option.
|
|
||||||
for _, b := range buckets {
|
|
||||||
g.buckets[b.name] = b
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
gcsErrs := sources.NewScanErrors()
|
|
||||||
for _, bucket := range g.buckets {
|
|
||||||
g.numBuckets++
|
|
||||||
bucket := bucket
|
|
||||||
g.workerPool.Go(func() error {
|
|
||||||
objCh, errCh := g.listBucketObjects(ctx, &bucket)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case obj, ok := <-objCh:
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ch <- obj
|
|
||||||
case err := <-errCh:
|
|
||||||
gcsErrs.Add(err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = g.workerPool.Wait()
|
|
||||||
if gcsErrs.Count() > 0 {
|
|
||||||
ctx.Logger().V(2).Info("encountered gcsErrs while scanning GCS buckets", "error-count", gcsErrs.Count(), "gcsErrs", gcsErrs.String())
|
|
||||||
}
|
|
||||||
close(ch)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return ch, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) listBuckets(ctx context.Context) ([]bucket, error) {
|
|
||||||
var buckets []bucket
|
|
||||||
if g.withoutAuth {
|
|
||||||
for name := range g.includeBuckets {
|
|
||||||
buckets = append(buckets, bucket{name: name})
|
|
||||||
}
|
|
||||||
return buckets, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bkts := g.client.Buckets(ctx, g.projectID)
|
|
||||||
for {
|
|
||||||
bkt, err := bkts.Next()
|
|
||||||
if errors.Is(err, iterator.Done) {
|
|
||||||
ctx.Logger().V(5).Info("finished listing buckets", "num_buckets", len(buckets))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to retrieve bucket: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the bucket is already in the map, skip it, it's already accounted for.
|
|
||||||
// This is used to resume listing objects for a bucket.
|
|
||||||
if _, ok := g.buckets[bkt.Name]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !g.shouldIncludeBucket(ctx, bkt.Name) || g.shouldExcludeBucket(ctx, bkt.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buckets = append(buckets, bucket{name: bkt.Name})
|
|
||||||
|
|
||||||
}
|
|
||||||
return buckets, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) listBucketObjects(ctx context.Context, bkt *bucket) (chan io.Reader, chan error) {
|
|
||||||
ch := make(chan io.Reader, 100)
|
|
||||||
errCh := make(chan error, 1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer close(ch)
|
|
||||||
|
|
||||||
logger := ctx.Logger().WithValues("bucket", bkt.name)
|
|
||||||
logger.V(5).Info("listing object(s) in bucket")
|
|
||||||
|
|
||||||
g.setupBktHandle(bkt)
|
|
||||||
|
|
||||||
// TODO (ahrav): Look to extend gcsManager to allow for exact buckets/objects
|
|
||||||
// include filters. This will increase performance substantially
|
|
||||||
|
|
||||||
if err := g.bucketObjects(ctx, bkt, ch); err != nil {
|
|
||||||
errCh <- fmt.Errorf("failed to list bucket objects: %w", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return ch, errCh
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) setupBktHandle(bkt *bucket) {
|
|
||||||
b := g.client.Bucket(bkt.name).Retryer(
|
|
||||||
storage.WithBackoff(gax.Backoff{
|
|
||||||
Initial: 2 * time.Second,
|
|
||||||
Max: 30 * time.Second,
|
|
||||||
Multiplier: 1.5,
|
|
||||||
}),
|
|
||||||
storage.WithPolicy(storage.RetryAlways),
|
|
||||||
)
|
|
||||||
bkt.BucketHandle = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) bucketObjects(ctx context.Context, bkt *bucket, ch chan<- io.Reader) error {
|
|
||||||
q, err := setObjectQuery(bkt)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to set object query: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objs := bkt.Objects(ctx, q)
|
|
||||||
for {
|
|
||||||
obj, err := objs.Next()
|
|
||||||
if errors.Is(err, iterator.Done) {
|
|
||||||
ctx.Logger().V(5).Info("finished listing objects in bucket")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to retrieve object iterator: %w", err)
|
|
||||||
}
|
|
||||||
if obj == nil {
|
|
||||||
ctx.Logger().V(5).Info("object is nil")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !g.shouldIncludeObject(ctx, obj.Name) || g.shouldExcludeObject(ctx, obj.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
o, err := g.constructObject(ctx, bkt.Object(obj.Name))
|
|
||||||
if err != nil {
|
|
||||||
ctx.Logger().V(1).Info("failed to create object", "object-name", obj.Name, "error", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ch <- o
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setObjectQuery(bkt *bucket) (*storage.Query, error) {
|
|
||||||
// Setting the attribute selection is a performance optimization.
|
|
||||||
// https://pkg.go.dev/cloud.google.com/go/storage#Query.SetAttrSelection
|
|
||||||
q := new(storage.Query)
|
|
||||||
err := q.SetAttrSelection([]string{
|
|
||||||
"Name",
|
|
||||||
"ContentType",
|
|
||||||
"Owner",
|
|
||||||
"Size",
|
|
||||||
"Updated",
|
|
||||||
"Created",
|
|
||||||
"ACL",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to set attribute selection: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a start offset is provided, then we need to set it on the query.
|
|
||||||
// This will begin listing objects from the start offset.
|
|
||||||
if bkt.startOffset != "" {
|
|
||||||
q.StartOffset = bkt.startOffset
|
|
||||||
}
|
|
||||||
return q, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) constructObject(ctx context.Context, obj *storage.ObjectHandle) (object, error) {
|
|
||||||
o := object{}
|
|
||||||
attrs, err := obj.Attrs(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return o, fmt.Errorf("failed to retrieve object attributes: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isObjectTypeValid(ctx, attrs.Name) || !g.isObjectSizeValid(ctx, attrs.Size) {
|
|
||||||
return o, fmt.Errorf("object is not valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
rc, err := obj.NewReader(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return o, fmt.Errorf("failed to retrieve object reader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
o.name = attrs.Name
|
|
||||||
o.bucket = attrs.Bucket
|
|
||||||
o.contentType = attrs.ContentType
|
|
||||||
o.owner = attrs.Owner
|
|
||||||
o.link = attrs.MediaLink
|
|
||||||
o.createdAt = attrs.Created
|
|
||||||
o.updatedAt = attrs.Updated
|
|
||||||
o.acl = objectACLs(attrs.ACL)
|
|
||||||
o.size = attrs.Size
|
|
||||||
o.Reader = rc
|
|
||||||
|
|
||||||
atomic.AddUint64(&g.numObjects, 1)
|
|
||||||
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func objectACLs(acl []storage.ACLRule) []string {
|
|
||||||
acls := make([]string, 0, len(acl))
|
|
||||||
for _, rule := range acl {
|
|
||||||
acls = append(acls, string(rule.Entity))
|
|
||||||
}
|
|
||||||
return acls
|
|
||||||
}
|
|
||||||
|
|
||||||
func isObjectTypeValid(ctx context.Context, name string) bool {
|
|
||||||
isValid := !common.SkipFile(name)
|
|
||||||
if !isValid {
|
|
||||||
ctx.Logger().V(2).Info("object type is invalid", "object-name", name)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) isObjectSizeValid(ctx context.Context, size int64) bool {
|
|
||||||
isValid := size > 0 && size <= g.maxObjectSize
|
|
||||||
if !isValid {
|
|
||||||
ctx.Logger().V(2).Info("object size is invalid", "object-size", size)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) shouldIncludeBucket(ctx context.Context, bkt string) bool {
|
|
||||||
if len(g.includeBuckets) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return shouldProcess(ctx, bkt, g.includeBuckets, globMatches)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) shouldExcludeBucket(ctx context.Context, bkt string) bool {
|
|
||||||
return shouldProcess(ctx, bkt, g.excludeBuckets, globMatches)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) shouldIncludeObject(ctx context.Context, obj string) bool {
|
|
||||||
if len(g.includeObjects) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return shouldProcess(ctx, obj, g.includeObjects, globMatches)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gcsManager) shouldExcludeObject(ctx context.Context, obj string) bool {
|
|
||||||
return shouldProcess(ctx, obj, g.excludeObjects, globMatches)
|
|
||||||
}
|
|
||||||
|
|
||||||
type globMatcherFn func(string, glob.Glob) bool
|
|
||||||
|
|
||||||
func shouldProcess(ctx context.Context, s string, matchers map[string]struct{}, matcherFn globMatcherFn) bool {
|
|
||||||
if len(matchers) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for m := range matchers {
|
|
||||||
g, err := glob.Compile(m)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Logger().V(1).Info("failed to compile glob", "glob", m, "error", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if matcherFn(s, g) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func globMatches(s string, g glob.Glob) bool {
|
|
||||||
return g.Match(s)
|
|
||||||
}
|
|
||||||
@@ -1,890 +0,0 @@
|
|||||||
package gcs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
publicBucket = "public-trufflehog-test-bucket"
|
|
||||||
testProjectID = "trufflehog-testing"
|
|
||||||
testAPIKey = "somekeys"
|
|
||||||
testBucket = "test-bkt-th"
|
|
||||||
testBucket2 = "test-bkt-th2"
|
|
||||||
testBucket3 = "test-bkt-th3"
|
|
||||||
testBucket4 = "test-bkt-th4"
|
|
||||||
perfTestBucketGlob = "perf-test-bkt-th*"
|
|
||||||
bucket1 = "bucket1"
|
|
||||||
bucket2 = "bucket2"
|
|
||||||
object1 = "object1"
|
|
||||||
object2 = "object2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNewGcsManager(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
projID string
|
|
||||||
opts []gcsManagerOption
|
|
||||||
want *gcsManager
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "new gcs manager, no options",
|
|
||||||
projID: testProjectID,
|
|
||||||
want: &gcsManager{projectID: testProjectID, concurrency: defaultConcurrency, maxObjectSize: defaultMaxObjectSize},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, no project id",
|
|
||||||
projID: "",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, without auth",
|
|
||||||
projID: "",
|
|
||||||
opts: []gcsManagerOption{withoutAuthentication()},
|
|
||||||
want: &gcsManager{
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
withoutAuth: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with api key",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withAPIKey(ctx, testAPIKey)},
|
|
||||||
want: &gcsManager{projectID: testProjectID, concurrency: defaultConcurrency, maxObjectSize: defaultMaxObjectSize},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with json service account",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withJSONServiceAccount(ctx, []byte(`{
|
|
||||||
"type": "service_account",
|
|
||||||
"project_id": "test-project"}`,
|
|
||||||
))},
|
|
||||||
want: &gcsManager{projectID: testProjectID, concurrency: defaultConcurrency, maxObjectSize: defaultMaxObjectSize},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with default ADC account",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx)},
|
|
||||||
want: &gcsManager{projectID: testProjectID, concurrency: defaultConcurrency, maxObjectSize: defaultMaxObjectSize},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with bucket offsets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withBucketOffsets(map[string]offsetInfo{
|
|
||||||
testBucket: {lastProcessedObject: "moar1.txt", isBucketProcessed: false},
|
|
||||||
testBucket2: {lastProcessedObject: "", isBucketProcessed: true}}),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
hasEnumerated: true,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
buckets: map[string]bucket{
|
|
||||||
testBucket: {name: testBucket, startOffset: "moar.txt", shouldInclude: true},
|
|
||||||
testBucket2: {name: testBucket2, startOffset: "", shouldInclude: false},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include buckets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeBuckets([]string{bucket1, bucket2}),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include buckets and api key",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withIncludeBuckets([]string{bucket1, bucket2}), withAPIKey(ctx, testAPIKey)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with exclude buckets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withExcludeBuckets([]string{bucket1, bucket2}), withAPIKey(ctx, testAPIKey)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
excludeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with exclude buckets and api key",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withExcludeBuckets([]string{bucket1, bucket2}), withAPIKey(ctx, testAPIKey)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
excludeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include and exclude buckets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeBuckets([]string{bucket1, bucket2}),
|
|
||||||
withExcludeBuckets([]string{"bucket3", "bucket4"}),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include and exclude buckets and api key",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeBuckets([]string{bucket1, bucket2}),
|
|
||||||
withExcludeBuckets([]string{"bucket3", "bucket4"}),
|
|
||||||
withAPIKey(ctx, testAPIKey),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include objects, no bucket",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withIncludeObjects([]string{"object1", "object2"})},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include objects, include buckets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeObjects([]string{"object1", "object2"}),
|
|
||||||
withIncludeBuckets([]string{bucket1, bucket2}),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include objects and api key, include buckets",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withIncludeObjects([]string{"object1", "object2"}),
|
|
||||||
withIncludeBuckets([]string{bucket1, bucket2}),
|
|
||||||
withAPIKey(ctx, testAPIKey),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
includeBuckets: map[string]struct{}{bucket1: {}, bucket2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with exclude objects",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withExcludeObjects([]string{"object1", "object2"})},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
excludeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with exclude objects and api key",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withExcludeObjects([]string{"object1", "object2"}), withAPIKey(ctx, testAPIKey)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
excludeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with include and exclude objects",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeObjects([]string{"object1", "object2"}),
|
|
||||||
withExcludeObjects([]string{"object3", "object4"}),
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeObjects: map[string]struct{}{object1: {}, object2: {}},
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with concurrency",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withConcurrency(10)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: 10,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, default concurrency",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with negative concurrency",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withConcurrency(-1)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with valid max object size",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withMaxObjectSize(10)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with negative max object size",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withMaxObjectSize(-1)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, max object size above limit",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withMaxObjectSize(int64(2 * common.GB))},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new gcs manager, with max object size 0",
|
|
||||||
projID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withMaxObjectSize(0)},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
concurrency: defaultConcurrency,
|
|
||||||
maxObjectSize: defaultMaxObjectSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
got, err := newGCSManager(tc.projID, tc.opts...)
|
|
||||||
if (err != nil) != tc.wantErr {
|
|
||||||
t.Errorf("newGCSManager() error = %v, wantErr %v", err, tc.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// The client should never be nil.
|
|
||||||
if got.client == nil {
|
|
||||||
t.Errorf("newGCSManager() client should not be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
diff := cmp.Diff(got, tc.want,
|
|
||||||
cmp.AllowUnexported(gcsManager{}, bucket{}),
|
|
||||||
cmpopts.IgnoreFields(gcsManager{}, "client", "workerPool", "buckets"),
|
|
||||||
)
|
|
||||||
if diff != "" {
|
|
||||||
t.Errorf("newGCSManager(%v, %v) got: %v, want: %v, diff: %v", tc.projID, tc.opts, got, tc.want, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGCSManagerStats(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
projectID string
|
|
||||||
opts []gcsManagerOption
|
|
||||||
wantStats *attributes
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "enumerate, all buckets, with objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withExcludeBuckets([]string{perfTestBucketGlob, publicBucket})},
|
|
||||||
wantStats: &attributes{
|
|
||||||
numBuckets: 4,
|
|
||||||
numObjects: 5,
|
|
||||||
bucketObjects: map[string]uint64{testBucket: 2, testBucket2: 1, testBucket3: 1, testBucket4: 1},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with exclude objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withExcludeObjects([]string{"aws1.txt", "moar2.txt"}),
|
|
||||||
withExcludeBuckets([]string{perfTestBucketGlob, publicBucket}),
|
|
||||||
},
|
|
||||||
wantStats: &attributes{
|
|
||||||
numBuckets: 4,
|
|
||||||
numObjects: 3,
|
|
||||||
bucketObjects: map[string]uint64{testBucket: 0, testBucket2: 1, testBucket3: 1, testBucket4: 1},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with include objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeObjects([]string{"aws1.txt"}),
|
|
||||||
withExcludeBuckets([]string{perfTestBucketGlob, publicBucket}),
|
|
||||||
},
|
|
||||||
wantStats: &attributes{
|
|
||||||
numBuckets: 4,
|
|
||||||
numObjects: 1,
|
|
||||||
bucketObjects: map[string]uint64{testBucket: 1, testBucket2: 0, testBucket3: 0, testBucket4: 0},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
gm, err := newGCSManager(tc.projectID, tc.opts...)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newGCSManager() error = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
got, err := gm.attributes(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("attributes() error = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if diff := cmp.Diff(got, tc.wantStats, cmp.AllowUnexported(attributes{}), cmpopts.IgnoreFields(attributes{}, "mu")); diff != "" {
|
|
||||||
t.Errorf("attributes() got: %v, want: %v, diff: %v", got, tc.wantStats, diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGCSManagerStats_Time(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
opts := []gcsManagerOption{withDefaultADC(ctx)}
|
|
||||||
gm, err := newGCSManager(testProjectID, opts...)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newGCSManager() error = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
var stats *attributes
|
|
||||||
stats, _ = gm.attributes(ctx)
|
|
||||||
end := time.Since(start).Seconds()
|
|
||||||
|
|
||||||
fmt.Printf("Time taken to get %d objects: %f seconds\n", stats.numObjects, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGCSManagerListObjects(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
projectID string
|
|
||||||
opts []gcsManagerOption
|
|
||||||
want []object
|
|
||||||
wantNumBkt uint32
|
|
||||||
wantNumObj uint64
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "list objects, all buckets, no objects",
|
|
||||||
projectID: "other",
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx)},
|
|
||||||
want: []object{},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, all buckets, with objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withExcludeBuckets([]string{perfTestBucketGlob, publicBucket})},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "aws1.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/aws1.txt?generation=1677870994890594&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar2.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 12,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/moar2.txt?generation=1677871000378542&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "aws3.txt",
|
|
||||||
bucket: testBucket2,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th2/o/aws3.txt?generation=1677871022489611&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar.txt",
|
|
||||||
bucket: testBucket3,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 6,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th3/o/moar.txt?generation=1677871042896804&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "AMAZON_FASHION_5.json",
|
|
||||||
bucket: testBucket4,
|
|
||||||
contentType: "application/json",
|
|
||||||
size: 1413469,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th4/o/AMAZON_FASHION_5.json?generation=1677871063457469&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 4,
|
|
||||||
wantNumObj: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, include buckets, with objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withIncludeBuckets([]string{testBucket})},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "aws1.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/aws1.txt?generation=1677870994890594&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar2.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 12,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/moar2.txt?generation=1677871000378542&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 1,
|
|
||||||
wantNumObj: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, exclude buckets, with objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{withDefaultADC(ctx), withExcludeBuckets([]string{testBucket, testBucket2, perfTestBucketGlob, publicBucket})},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "moar.txt",
|
|
||||||
bucket: testBucket3,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 6,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th3/o/moar.txt?generation=1677871042896804&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "AMAZON_FASHION_5.json",
|
|
||||||
bucket: testBucket4,
|
|
||||||
contentType: "application/json",
|
|
||||||
size: 1413469,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th4/o/AMAZON_FASHION_5.json?generation=1677871063457469&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 2,
|
|
||||||
wantNumObj: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with exclude objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withExcludeObjects([]string{"aws1.txt", "moar2.txt"}),
|
|
||||||
withExcludeBuckets([]string{perfTestBucketGlob, publicBucket}),
|
|
||||||
},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "aws3.txt",
|
|
||||||
bucket: testBucket2,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th2/o/aws3.txt?generation=1677871022489611&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "moar.txt",
|
|
||||||
bucket: testBucket3,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 6,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th3/o/moar.txt?generation=1677871042896804&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "AMAZON_FASHION_5.json",
|
|
||||||
bucket: testBucket4,
|
|
||||||
contentType: "application/json",
|
|
||||||
size: 1413469,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th4/o/AMAZON_FASHION_5.json?generation=1677871063457469&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 4, // We still list objects in all buckets.
|
|
||||||
wantNumObj: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with include objects, include bucket",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeObjects([]string{"aws1.txt"}),
|
|
||||||
withIncludeBuckets([]string{testBucket}),
|
|
||||||
},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "aws1.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/aws1.txt?generation=1677870994890594&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 1,
|
|
||||||
wantNumObj: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with include objects",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeObjects([]string{"aws1.txt"}),
|
|
||||||
withExcludeBuckets([]string{perfTestBucketGlob, publicBucket}),
|
|
||||||
},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "aws1.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 150,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/aws1.txt?generation=1677870994890594&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 4,
|
|
||||||
wantNumObj: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list objects, with include bucket, exclude object",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeBuckets([]string{testBucket}),
|
|
||||||
withExcludeObjects([]string{"aws1.txt"}),
|
|
||||||
withExcludeBuckets([]string{perfTestBucketGlob, publicBucket}),
|
|
||||||
},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "moar2.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 12,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/moar2.txt?generation=1677871000378542&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 1,
|
|
||||||
wantNumObj: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
mgr, err := newGCSManager(tc.projectID, tc.opts...)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
got, err := mgr.listObjects(ctx)
|
|
||||||
if (err != nil) != tc.wantErr {
|
|
||||||
t.Errorf("GCSManager.ListObjects() error = %v, wantErr %v", err, tc.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we expect an error, we're done.
|
|
||||||
// Short-circuit the rest of the test.
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
doneCh := make(chan struct{})
|
|
||||||
defer close(doneCh)
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
doneCh <- struct{}{}
|
|
||||||
}()
|
|
||||||
res := make([]object, 0, len(tc.want))
|
|
||||||
for obj := range got {
|
|
||||||
res = append(res, obj.(object))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) != len(tc.want) {
|
|
||||||
t.Errorf("gcsManager.listObjects() got: %v, want: %v", res, tc.want)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the bucket and object counts.
|
|
||||||
assert.Equal(t, tc.wantNumBkt, mgr.numBuckets)
|
|
||||||
assert.Equal(t, tc.wantNumObj, mgr.numObjects)
|
|
||||||
|
|
||||||
// Sort the objects by name to make the test deterministic.
|
|
||||||
// This is necessary because we list bucket objects concurrently.
|
|
||||||
sort.Slice(res, func(i, j int) bool { return res[i].name < res[j].name })
|
|
||||||
sort.Slice(tc.want, func(i, j int) bool { return tc.want[i].name < tc.want[j].name })
|
|
||||||
|
|
||||||
// Test the objects are equal.
|
|
||||||
if diff := cmp.Diff(res, tc.want, cmp.AllowUnexported(object{}), cmpopts.IgnoreFields(object{}, "Reader", "createdAt", "updatedAt")); diff != "" {
|
|
||||||
t.Errorf("gcsManager.listObjects() mismatch (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-doneCh
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGCSManagerListObjects_Resuming(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
projectID string
|
|
||||||
opts []gcsManagerOption
|
|
||||||
want []object
|
|
||||||
wantNumBkt uint32
|
|
||||||
wantNumObj uint64
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "list objects, testBucket, resume from moar2.txt",
|
|
||||||
projectID: testProjectID,
|
|
||||||
opts: []gcsManagerOption{
|
|
||||||
withDefaultADC(ctx),
|
|
||||||
withIncludeBuckets([]string{testBucket}),
|
|
||||||
withBucketOffsets(map[string]offsetInfo{testBucket: {lastProcessedObject: "moar2.txt"}}),
|
|
||||||
},
|
|
||||||
want: []object{
|
|
||||||
{
|
|
||||||
name: "moar2.txt",
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "text/plain",
|
|
||||||
size: 12,
|
|
||||||
link: "https://storage.googleapis.com/download/storage/v1/b/test-bkt-th/o/moar2.txt?generation=1677871000378542&alt=media",
|
|
||||||
acl: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantNumBkt: 1,
|
|
||||||
wantNumObj: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
mgr, err := newGCSManager(tc.projectID, tc.opts...)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
got, err := mgr.listObjects(ctx)
|
|
||||||
if (err != nil) != tc.wantErr {
|
|
||||||
t.Errorf("GCSManager.ListObjects() error = %v, wantErr %v", err, tc.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we expect an error, we're done.
|
|
||||||
// Short-circuit the rest of the test.
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
doneCh := make(chan struct{})
|
|
||||||
defer close(doneCh)
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
doneCh <- struct{}{}
|
|
||||||
}()
|
|
||||||
res := make([]object, 0, len(tc.want))
|
|
||||||
for obj := range got {
|
|
||||||
res = append(res, obj.(object))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) != len(tc.want) {
|
|
||||||
t.Errorf("gcsManager.listObjects() got: %v, want: %v", res, tc.want)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the bucket and object counts.
|
|
||||||
assert.Equal(t, tc.wantNumBkt, mgr.numBuckets)
|
|
||||||
assert.Equal(t, tc.wantNumObj, mgr.numObjects)
|
|
||||||
|
|
||||||
// Sort the objects by name to make the test deterministic.
|
|
||||||
// This is necessary because we list bucket objects concurrently.
|
|
||||||
sort.Slice(res, func(i, j int) bool { return res[i].name < res[j].name })
|
|
||||||
sort.Slice(tc.want, func(i, j int) bool { return tc.want[i].name < tc.want[j].name })
|
|
||||||
|
|
||||||
// Test the objects are equal.
|
|
||||||
if diff := cmp.Diff(res, tc.want, cmp.AllowUnexported(object{}), cmpopts.IgnoreFields(object{}, "Reader", "createdAt", "updatedAt")); diff != "" {
|
|
||||||
t.Errorf("gcsManager.listObjects() mismatch (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-doneCh
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_isObjectTypeValid(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
objName string
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "valid object type, text",
|
|
||||||
objName: "aws1.txt",
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid object type, zip",
|
|
||||||
objName: "aws1.zip",
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid object type",
|
|
||||||
objName: "video.mp4",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
got := isObjectTypeValid(ctx, tc.objName)
|
|
||||||
assert.Equal(t, tc.want, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_isObjectSizeValid(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
objSize int64
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "valid object size, 150 bytes",
|
|
||||||
objSize: 150,
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid object size, 1 MB",
|
|
||||||
objSize: int64(1 * common.MB),
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid object size, 49 MB",
|
|
||||||
objSize: int64(49 * common.MB),
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid object size, 1 GB",
|
|
||||||
objSize: int64(1 * common.GB),
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid object size, 2 GB",
|
|
||||||
objSize: int64(2 * common.GB),
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid object size, empty object",
|
|
||||||
objSize: 0,
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid object size, negative object size",
|
|
||||||
objSize: -1,
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
for _, tc := range testCases {
|
|
||||||
g := &gcsManager{
|
|
||||||
maxObjectSize: maxObjectSizeLimit,
|
|
||||||
}
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
got := g.isObjectSizeValid(ctx, tc.objSize)
|
|
||||||
assert.Equal(t, tc.want, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,291 +0,0 @@
|
|||||||
package gcs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"google.golang.org/protobuf/types/known/anypb"
|
|
||||||
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
|
||||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createTestSource(src *sourcespb.GCS) (*Source, *anypb.Any) {
|
|
||||||
s := &Source{}
|
|
||||||
conn, err := anypb.New(src)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return s, conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSourceInit(t *testing.T) {
|
|
||||||
source, conn := createTestSource(&sourcespb.GCS{
|
|
||||||
ProjectId: testProjectID,
|
|
||||||
IncludeBuckets: []string{
|
|
||||||
publicBucket,
|
|
||||||
},
|
|
||||||
ExcludeBuckets: []string{
|
|
||||||
perfTestBucketGlob,
|
|
||||||
},
|
|
||||||
ExcludeObjects: []string{
|
|
||||||
"object1",
|
|
||||||
},
|
|
||||||
Credential: &sourcespb.GCS_Unauthenticated{},
|
|
||||||
})
|
|
||||||
|
|
||||||
err := source.Init(context.Background(), "test", 1, 1, true, conn, 8)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.NotNil(t, source.gcsManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfigureGCSManager(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
conn *sourcespb.GCS
|
|
||||||
want *gcsManager
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "nil conn",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid conn, bare config",
|
|
||||||
conn: &sourcespb.GCS{
|
|
||||||
ProjectId: testProjectID,
|
|
||||||
Credential: &sourcespb.GCS_Adc{},
|
|
||||||
ExcludeBuckets: []string{
|
|
||||||
perfTestBucketGlob,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
excludeBuckets: map[string]struct{}{perfTestBucketGlob: {}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid conn, include and exclude buckets",
|
|
||||||
conn: &sourcespb.GCS{
|
|
||||||
ProjectId: testProjectID,
|
|
||||||
Credential: &sourcespb.GCS_Adc{},
|
|
||||||
IncludeBuckets: []string{
|
|
||||||
"bucket1",
|
|
||||||
},
|
|
||||||
ExcludeBuckets: []string{
|
|
||||||
perfTestBucketGlob,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeBuckets: map[string]struct{}{"bucket1": {}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "valid conn, include and exclude objects",
|
|
||||||
conn: &sourcespb.GCS{
|
|
||||||
ProjectId: testProjectID,
|
|
||||||
Credential: &sourcespb.GCS_Adc{},
|
|
||||||
IncludeObjects: []string{
|
|
||||||
"object1",
|
|
||||||
},
|
|
||||||
ExcludeObjects: []string{
|
|
||||||
"object2",
|
|
||||||
},
|
|
||||||
ExcludeBuckets: []string{
|
|
||||||
perfTestBucketGlob,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: &gcsManager{
|
|
||||||
projectID: testProjectID,
|
|
||||||
includeObjects: map[string]struct{}{"object1": {}},
|
|
||||||
excludeBuckets: map[string]struct{}{perfTestBucketGlob: {}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
got, err := configureGCSManager(ctx, tc.conn, 8)
|
|
||||||
if err != nil && !tc.wantErr {
|
|
||||||
t.Errorf("source.configureGCSManager() error = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tc.wantErr {
|
|
||||||
if diff := cmp.Diff(tc.want, got,
|
|
||||||
cmp.AllowUnexported(gcsManager{}),
|
|
||||||
cmpopts.IgnoreFields(gcsManager{}, "client", "workerPool", "concurrency", "buckets", "maxObjectSize", "attr"),
|
|
||||||
); diff != "" {
|
|
||||||
t.Errorf("source.Init() diff: (-want +got)\n%s", diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockObjectManager struct {
|
|
||||||
wantErr bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockObjectManager) attributes(_ context.Context) (*attributes, error) {
|
|
||||||
if m.wantErr {
|
|
||||||
return nil, fmt.Errorf("some error")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &attributes{
|
|
||||||
numObjects: 5,
|
|
||||||
numBuckets: 1,
|
|
||||||
bucketObjects: map[string]uint64{testBucket: 5},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockReader struct {
|
|
||||||
offset int
|
|
||||||
data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockReader) Read(p []byte) (n int, err error) {
|
|
||||||
if m.offset >= len(m.data) {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
n = copy(p, m.data[m.offset:])
|
|
||||||
m.offset += n
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockObjectManager) listObjects(context.Context) (chan io.Reader, error) {
|
|
||||||
if m.wantErr {
|
|
||||||
return nil, fmt.Errorf("some error")
|
|
||||||
}
|
|
||||||
|
|
||||||
ch := make(chan io.Reader)
|
|
||||||
go func() {
|
|
||||||
defer close(ch)
|
|
||||||
// Add 5 objects to the channel.
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
ch <- createTestObject(i)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return ch, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestObject(id int) object {
|
|
||||||
return object{
|
|
||||||
name: fmt.Sprintf("object%d", id),
|
|
||||||
bucket: testBucket,
|
|
||||||
contentType: "plain/text",
|
|
||||||
owner: "testman@test.com",
|
|
||||||
link: fmt.Sprintf("https://storage.googleapis.com/%s/%s", testBucket, fmt.Sprintf("object%d", id)),
|
|
||||||
acl: []string{"authenticatedUsers"},
|
|
||||||
size: 42,
|
|
||||||
Reader: &mockReader{data: []byte(fmt.Sprintf("hello world %d", id))},
|
|
||||||
createdAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestSourceChunk(id int) *sources.Chunk {
|
|
||||||
return &sources.Chunk{
|
|
||||||
SourceName: "test",
|
|
||||||
SourceType: sourcespb.SourceType_SOURCE_TYPE_GCS,
|
|
||||||
SourceID: 0,
|
|
||||||
Verify: true,
|
|
||||||
Data: []byte(fmt.Sprintf("hello world %d", id)),
|
|
||||||
SourceMetadata: &source_metadatapb.MetaData{
|
|
||||||
Data: &source_metadatapb.MetaData_Gcs{
|
|
||||||
Gcs: &source_metadatapb.GCS{
|
|
||||||
Filename: fmt.Sprintf("object%d", id),
|
|
||||||
Bucket: testBucket,
|
|
||||||
ContentType: "plain/text",
|
|
||||||
Email: "testman@test.com",
|
|
||||||
Link: fmt.Sprintf("https://storage.googleapis.com/%s/%s", testBucket, fmt.Sprintf("object%d", id)),
|
|
||||||
Acls: []string{"authenticatedUsers"},
|
|
||||||
CreatedAt: "1577836800",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSourceChunks_ListObjects(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
chunksCh := make(chan *sources.Chunk, 1)
|
|
||||||
|
|
||||||
source := &Source{
|
|
||||||
gcsManager: &mockObjectManager{},
|
|
||||||
chunksCh: chunksCh,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := source.enumerate(ctx)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer close(chunksCh)
|
|
||||||
err := source.Chunks(ctx, chunksCh)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
want := make([]*sources.Chunk, 0, 5)
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
want = append(want, createTestSourceChunk(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
got := make([]*sources.Chunk, 0, 5)
|
|
||||||
for ch := range chunksCh {
|
|
||||||
got = append(got, ch)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we get 5 objects back.
|
|
||||||
assert.Equal(t, 5, count)
|
|
||||||
|
|
||||||
// Sort the results to ensure deterministic ordering.
|
|
||||||
sort.Slice(want, func(i, j int) bool {
|
|
||||||
return want[i].SourceMetadata.GetGcs().Filename < want[j].SourceMetadata.GetGcs().Filename
|
|
||||||
})
|
|
||||||
sort.Slice(got, func(i, j int) bool {
|
|
||||||
return got[i].SourceMetadata.GetGcs().Filename < got[j].SourceMetadata.GetGcs().Filename
|
|
||||||
})
|
|
||||||
|
|
||||||
for i, c := range got {
|
|
||||||
assert.Equal(t, want[i].SourceMetadata.GetGcs().Filename, c.SourceMetadata.GetGcs().Filename)
|
|
||||||
assert.Equal(t, want[i].Data, c.Data)
|
|
||||||
assert.Equal(t, want[i].SourceMetadata.GetGcs().CreatedAt, c.SourceMetadata.GetGcs().CreatedAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSourceInit_Enumerate(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
source := &Source{gcsManager: &mockObjectManager{}}
|
|
||||||
|
|
||||||
err := source.enumerate(ctx)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
// Ensure the attributes are set.
|
|
||||||
assert.Equal(t, uint64(5), source.stats.numObjects)
|
|
||||||
assert.Equal(t, uint32(1), source.stats.numBuckets)
|
|
||||||
assert.Equal(t, uint64(5), source.stats.bucketObjects[testBucket])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSourceChunks_ListObjects_Error(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
source := &Source{gcsManager: &mockObjectManager{wantErr: true}}
|
|
||||||
|
|
||||||
chunksCh := make(chan *sources.Chunk, 1)
|
|
||||||
|
|
||||||
defer close(chunksCh)
|
|
||||||
err := source.Chunks(ctx, chunksCh)
|
|
||||||
assert.True(t, err != nil)
|
|
||||||
}
|
|
||||||
@@ -295,7 +295,7 @@ func CloneRepo(ctx context.Context, userInfo *url.Userinfo, gitUrl string, args
|
|||||||
return "", nil, errors.New("clone command exited with no output")
|
return "", nil, errors.New("clone command exited with no output")
|
||||||
}
|
}
|
||||||
if cloneCmd.ProcessState != nil && cloneCmd.ProcessState.ExitCode() != 0 {
|
if cloneCmd.ProcessState != nil && cloneCmd.ProcessState.ExitCode() != 0 {
|
||||||
logger.V(1).Info("git clone failed", "output", output, "error", err)
|
logger.V(1).Info("git clone failed", "error", err)
|
||||||
return "", nil, fmt.Errorf("could not clone repo: %s, %w", safeUrl, err)
|
return "", nil, fmt.Errorf("could not clone repo: %s, %w", safeUrl, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ func (s *Git) ScanCommits(ctx context.Context, repo *git.Repository, path string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitChan, err := gitparse.NewParser().RepoPath(ctx, path, scanOptions.HeadHash, scanOptions.BaseHash == "", scanOptions.ExcludeGlobs)
|
commitChan, err := gitparse.NewParser().RepoPath(ctx, path, scanOptions.HeadHash, scanOptions.BaseHash == "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -378,7 +378,7 @@ func (s *Git) ScanCommits(ctx context.Context, repo *git.Repository, path string
|
|||||||
var email, hash, when string
|
var email, hash, when string
|
||||||
email = commit.Author
|
email = commit.Author
|
||||||
hash = commit.Hash
|
hash = commit.Hash
|
||||||
when = commit.Date.Format("2006-01-02 15:04:05 -0700")
|
when = commit.Date.String()
|
||||||
|
|
||||||
// Handle binary files by reading the entire file rather than using the diff.
|
// Handle binary files by reading the entire file rather than using the diff.
|
||||||
if diff.IsBinary {
|
if diff.IsBinary {
|
||||||
@@ -520,7 +520,7 @@ func (s *Git) ScanStaged(ctx context.Context, repo *git.Repository, path string,
|
|||||||
var email, hash, when string
|
var email, hash, when string
|
||||||
email = commit.Author
|
email = commit.Author
|
||||||
hash = commit.Hash
|
hash = commit.Hash
|
||||||
when = commit.Date.Format("2006-01-02 15:04:05 -0700")
|
when = commit.Date.String()
|
||||||
|
|
||||||
// Handle binary files by reading the entire file rather than using the diff.
|
// Handle binary files by reading the entire file rather than using the diff.
|
||||||
if diff.IsBinary {
|
if diff.IsBinary {
|
||||||
|
|||||||
@@ -6,12 +6,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ScanOptions struct {
|
type ScanOptions struct {
|
||||||
Filter *common.Filter
|
Filter *common.Filter
|
||||||
BaseHash string // When scanning a git.Log, this is the oldest/first commit.
|
BaseHash string // When scanning a git.Log, this is the oldest/first commit.
|
||||||
HeadHash string
|
HeadHash string
|
||||||
MaxDepth int64
|
MaxDepth int64
|
||||||
ExcludeGlobs []string
|
LogOptions *git.LogOptions
|
||||||
LogOptions *git.LogOptions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScanOption func(*ScanOptions)
|
type ScanOption func(*ScanOptions)
|
||||||
@@ -40,12 +39,6 @@ func ScanOptionMaxDepth(maxDepth int64) ScanOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanOptionExcludeGlobs(globs []string) ScanOption {
|
|
||||||
return func(scanOptions *ScanOptions) {
|
|
||||||
scanOptions.ExcludeGlobs = globs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScanOptionLogOptions(logOptions *git.LogOptions) ScanOption {
|
func ScanOptionLogOptions(logOptions *git.LogOptions) ScanOption {
|
||||||
return func(scanOptions *ScanOptions) {
|
return func(scanOptions *ScanOptions) {
|
||||||
scanOptions.LogOptions = logOptions
|
scanOptions.LogOptions = logOptions
|
||||||
|
|||||||
@@ -44,33 +44,6 @@ type Source interface {
|
|||||||
GetProgress() *Progress
|
GetProgress() *Progress
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCSConfig defines the optional configuration for a GCS source.
|
|
||||||
type GCSConfig struct {
|
|
||||||
// CloudCred determines whether to use cloud credentials.
|
|
||||||
// This can NOT be used with a secret.
|
|
||||||
CloudCred,
|
|
||||||
// WithoutAuth is a flag to indicate whether to use authentication.
|
|
||||||
WithoutAuth bool
|
|
||||||
// ApiKey is the API key to use to authenticate with the source.
|
|
||||||
ApiKey,
|
|
||||||
// ProjectID is the project ID to use to authenticate with the source.
|
|
||||||
ProjectID,
|
|
||||||
// ServiceAccount is the service account to use to authenticate with the source.
|
|
||||||
ServiceAccount string
|
|
||||||
// MaxObjectSize is the maximum object size to scan.
|
|
||||||
MaxObjectSize int64
|
|
||||||
// Concurrency is the number of concurrent workers to use to scan the source.
|
|
||||||
Concurrency int
|
|
||||||
// IncludeBuckets is a list of buckets to include in the scan.
|
|
||||||
IncludeBuckets,
|
|
||||||
// ExcludeBuckets is a list of buckets to exclude from the scan.
|
|
||||||
ExcludeBuckets,
|
|
||||||
// IncludeObjects is a list of objects to include in the scan.
|
|
||||||
IncludeObjects,
|
|
||||||
// ExcludeObjects is a list of objects to exclude from the scan.
|
|
||||||
ExcludeObjects []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// GitConfig defines the optional configuration for a git source.
|
// GitConfig defines the optional configuration for a git source.
|
||||||
type GitConfig struct {
|
type GitConfig struct {
|
||||||
// RepoPath is the path to the repository to scan.
|
// RepoPath is the path to the repository to scan.
|
||||||
@@ -83,9 +56,6 @@ type GitConfig struct {
|
|||||||
MaxDepth int
|
MaxDepth int
|
||||||
// Filter is the filter to use to scan the source.
|
// Filter is the filter to use to scan the source.
|
||||||
Filter *common.Filter
|
Filter *common.Filter
|
||||||
// ExcludeGlobs is a list of globs to exclude from the scan.
|
|
||||||
// This differs from the Filter exclusions as ExcludeGlobs is applied at the `git log -p` level
|
|
||||||
ExcludeGlobs []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GithubConfig defines the optional configuration for a github source.
|
// GithubConfig defines the optional configuration for a github source.
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ message Oauth2 {
|
|||||||
string refresh_token = 1;
|
string refresh_token = 1;
|
||||||
string client_id = 2;
|
string client_id = 2;
|
||||||
string client_secret = 3;
|
string client_secret = 3;
|
||||||
string access_token = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message KeySecret {
|
message KeySecret {
|
||||||
|
|||||||
@@ -912,13 +912,6 @@ enum DetectorType {
|
|||||||
Shopify = 902;
|
Shopify = 902;
|
||||||
RabbitMQ = 903;
|
RabbitMQ = 903;
|
||||||
CustomRegex = 904;
|
CustomRegex = 904;
|
||||||
Etherscan = 905;
|
|
||||||
Infura = 906;
|
|
||||||
Alchemy = 907;
|
|
||||||
BlockNative = 908;
|
|
||||||
Moralis = 909;
|
|
||||||
BscScan = 910;
|
|
||||||
CoinMarketCap = 911;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Result {
|
message Result {
|
||||||
|
|||||||
@@ -122,13 +122,9 @@ message GoogleDrive {
|
|||||||
|
|
||||||
message GCS {
|
message GCS {
|
||||||
string bucket = 1;
|
string bucket = 1;
|
||||||
string filename = 2;
|
string file = 2;
|
||||||
string link = 3;
|
string link = 3;
|
||||||
string email = 4;
|
string email = 4;
|
||||||
string created_at = 5;
|
|
||||||
string updated_at = 6;
|
|
||||||
repeated string acls = 7;
|
|
||||||
string content_type = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Jira {
|
message Jira {
|
||||||
|
|||||||
+2
-13
@@ -41,7 +41,6 @@ enum SourceType {
|
|||||||
SOURCE_TYPE_PUBLIC_EVENT_MONITORING = 26;
|
SOURCE_TYPE_PUBLIC_EVENT_MONITORING = 26;
|
||||||
SOURCE_TYPE_SLACK_REALTIME = 27;
|
SOURCE_TYPE_SLACK_REALTIME = 27;
|
||||||
SOURCE_TYPE_GOOGLE_DRIVE = 28;
|
SOURCE_TYPE_GOOGLE_DRIVE = 28;
|
||||||
SOURCE_TYPE_GCS_UNAUTHED = 30;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message LocalSource {
|
message LocalSource {
|
||||||
@@ -126,19 +125,9 @@ message Filesystem {
|
|||||||
|
|
||||||
message GCS {
|
message GCS {
|
||||||
oneof credential {
|
oneof credential {
|
||||||
string json_service_account = 1;
|
string json_sa = 1;
|
||||||
string api_key = 2;
|
|
||||||
credentials.Unauthenticated unauthenticated = 3;
|
|
||||||
credentials.CloudEnvironment adc = 4;
|
|
||||||
string service_account_file = 11;
|
|
||||||
credentials.Oauth2 oauth = 12;
|
|
||||||
}
|
}
|
||||||
string project_id = 5;
|
repeated string buckets = 2;
|
||||||
repeated string include_buckets = 6;
|
|
||||||
repeated string exclude_buckets = 7;
|
|
||||||
repeated string include_objects = 8;
|
|
||||||
repeated string exclude_objects = 9;
|
|
||||||
int64 max_object_size = 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Git {
|
message Git {
|
||||||
|
|||||||
Reference in New Issue
Block a user