adding customizable successRanges and rotatedRanges to customDetector (#4892)
Test / test (push) Waiting to run
Scan for secrets / test (push) Waiting to run
Test / test-community (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Lint / man-page-staleness (push) Waiting to run
Lint / semgrep (push) Waiting to run
Lint / checksecretparts (push) Waiting to run
Release / mark-latest (push) Canceled after 0s
Release / Release (push) Canceled after 0s
Test / test (push) Waiting to run
Scan for secrets / test (push) Waiting to run
Test / test-community (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Lint / man-page-staleness (push) Waiting to run
Lint / semgrep (push) Waiting to run
Lint / checksecretparts (push) Waiting to run
Release / mark-latest (push) Canceled after 0s
Release / Release (push) Canceled after 0s
* adding customizable successRanges and rotatedRanges to customDetector *setting definitive = true in the legacy 200 path so that an earlier ranged verifier's rangesInEffect = true can't trigger a spurious SetVerificationError after the legacy verifier already confirmed the secret as live. * adressed review comments
This commit is contained in:
@@ -36,6 +36,34 @@ This guide will walk you through setting up a custom detector in TruffleHog to i
|
||||
- **`regex`**: Defines the patterns to identify potential secrets. You can specify one or more named regular expressions. For a detection to be successful, each named regex must find a match. Capture groups `()` within these regular expressions are used to extract specific portions of the matched text, enabling the detector to process and report on particular segments of the identified patterns.
|
||||
|
||||
- **`verify`**: An optional section to validate detected secrets. If you want to verify or unverify detected secrets, this section needs to be configured. If not configured, all detected secrets will be marked as unverified. Read [verification server examples](#verification-server-examples)
|
||||
- **`successRanges`**: A list of HTTP status codes (or ranges) that indicate the secret is **live** (active). When the verification server responds with a matching status code, the secret is marked as verified. Each entry can be a single code (`"200"`) or an inclusive range (`"200-202"`). If omitted (along with `rotatedRanges`), only `200` is treated as verified (backward compatible).
|
||||
- **`rotatedRanges`**: A list of HTTP status codes (or ranges) that indicate the secret has been **rotated** (no longer active). When the verification server responds with a matching status code, the secret is definitively marked as unverified.
|
||||
|
||||
When only one of the two fields is configured, non-matching responses are treated as the opposite state (e.g., if only `successRanges` is set, any response that doesn't match is treated as rotated; if only `rotatedRanges` is set, any non-matching response is treated as live). When both fields are configured and the response matches neither, the result is treated as unknown/inconclusive.
|
||||
|
||||
Here's an example with configurable verification ranges:
|
||||
|
||||
```yaml
|
||||
# config.yaml
|
||||
detectors:
|
||||
- name: HogTokenDetector
|
||||
keywords:
|
||||
- hog
|
||||
regex:
|
||||
token: '[^A-Za-z0-9+\/]{0,1}([A-Za-z0-9+\/]{40})[^A-Za-z0-9+\/]{0,1}'
|
||||
verify:
|
||||
- endpoint: http://localhost:8000/
|
||||
unsafe: true
|
||||
headers:
|
||||
- "Authorization: super secret authorization header"
|
||||
successRanges:
|
||||
- "200"
|
||||
rotatedRanges:
|
||||
- "401"
|
||||
- "403"
|
||||
```
|
||||
|
||||
In this example, a `200` response from the verification server means the secret is live and needs rotation. A `401` or `403` means the secret has been rotated and is no longer active. Any other response is treated as inconclusive.
|
||||
|
||||
**Other allowed parameters:**
|
||||
- **`primary_regex_name`**: This parameter allows you designate the primary regex pattern when multiple regex patterns are defined in the regex section. If a match is found, the match for the designated primary regex will be used to determine the line number. The value must be one of the names specified in the regex section. If not provided, the first regex name in sorted order will be used as the primary regex by default.
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"maps"
|
||||
"net/http"
|
||||
@@ -64,6 +65,12 @@ func NewWebhookCustomRegex(pb *custom_detectorspb.CustomRegex) (*CustomRegexWebh
|
||||
if err := ValidateVerifyHeaders(verify.Headers); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidateVerifyRanges(verify.SuccessRanges); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidateVerifyRanges(verify.RotatedRanges); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure primary regex name is set.
|
||||
@@ -275,10 +282,15 @@ func (c *CustomRegexWebhook) createResults(ctx context.Context, match map[string
|
||||
// disrupt other verification.
|
||||
return nil
|
||||
}
|
||||
// Try each config until we successfully verify.
|
||||
|
||||
var (
|
||||
definitive bool
|
||||
rangesInEffect bool
|
||||
)
|
||||
|
||||
// Try each config until we get a definitive answer.
|
||||
for _, verifyConfig := range c.GetVerify() {
|
||||
if common.IsDone(ctx) {
|
||||
// TODO: Log we're possibly leaving out results.
|
||||
return ctx.Err()
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", verifyConfig.GetEndpoint(), bytes.NewReader(jsonBody))
|
||||
@@ -288,7 +300,6 @@ func (c *CustomRegexWebhook) createResults(ctx context.Context, match map[string
|
||||
for _, header := range verifyConfig.GetHeaders() {
|
||||
key, value, found := strings.Cut(header, ":")
|
||||
if !found {
|
||||
// Should be unreachable due to validation.
|
||||
continue
|
||||
}
|
||||
req.Header.Add(key, strings.TrimLeft(value, "\t\n\v\f\r "))
|
||||
@@ -305,27 +316,58 @@ func (c *CustomRegexWebhook) createResults(ctx context.Context, match map[string
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
// mark the result as verified
|
||||
successRanges := verifyConfig.GetSuccessRanges()
|
||||
rotatedRanges := verifyConfig.GetRotatedRanges()
|
||||
|
||||
if len(successRanges) == 0 && len(rotatedRanges) == 0 {
|
||||
// Backward compat: no ranges configured, use legacy behavior.
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
result.Verified = true
|
||||
definitive = true
|
||||
storeResponseBody(resp, result.ExtraData)
|
||||
break
|
||||
}
|
||||
// Legacy non-200 is a meaningful response (verifier said "no");
|
||||
// mark definitive so a prior ranged verifier with rangesInEffect
|
||||
// does not cause a spurious verification error.
|
||||
definitive = true
|
||||
continue
|
||||
}
|
||||
|
||||
rangesInEffect = true
|
||||
bothConfigured := len(successRanges) > 0 && len(rotatedRanges) > 0
|
||||
|
||||
if StatusCodeMatchesRanges(resp.StatusCode, successRanges) {
|
||||
result.Verified = true
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: handle different content-type responses seperatly when implement custom detector configurations
|
||||
responseStr := string(body)
|
||||
// truncate to 200 characters if response length exceeds 200
|
||||
if len(responseStr) > 200 {
|
||||
responseStr = responseStr[:200]
|
||||
}
|
||||
|
||||
// store the processed response in ExtraData
|
||||
result.ExtraData["response"] = responseStr
|
||||
|
||||
definitive = true
|
||||
storeResponseBody(resp, result.ExtraData)
|
||||
break
|
||||
}
|
||||
|
||||
if StatusCodeMatchesRanges(resp.StatusCode, rotatedRanges) {
|
||||
definitive = true
|
||||
break
|
||||
}
|
||||
|
||||
// Status matched neither configured range.
|
||||
if !bothConfigured {
|
||||
// Only one side was configured: the non-matching response is
|
||||
// treated as the opposite state.
|
||||
// successRanges only -> non-match means rotated
|
||||
// rotatedRanges only -> non-match means live
|
||||
definitive = true
|
||||
if len(rotatedRanges) > 0 {
|
||||
result.Verified = true
|
||||
storeResponseBody(resp, result.ExtraData)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// Both configured but neither matched -- try the next verifier.
|
||||
}
|
||||
|
||||
if rangesInEffect && !definitive {
|
||||
result.SetVerificationError(errors.New("verification response status code did not match any configured successRanges or rotatedRanges"))
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -336,6 +378,20 @@ func (c *CustomRegexWebhook) createResults(ctx context.Context, match map[string
|
||||
}
|
||||
}
|
||||
|
||||
const maxResponseLen = 200
|
||||
|
||||
func storeResponseBody(resp *http.Response, extraData map[string]string) {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
responseStr := string(body)
|
||||
if len(responseStr) > maxResponseLen {
|
||||
responseStr = responseStr[:maxResponseLen]
|
||||
}
|
||||
extraData["response"] = responseStr
|
||||
}
|
||||
|
||||
func (c *CustomRegexWebhook) Keywords() []string {
|
||||
return c.GetKeywords()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package custom_detectors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -47,6 +49,30 @@ verify:
|
||||
assert.Equal(t, []string{"200-250", "288"}, got.Verify[0].SuccessRanges)
|
||||
}
|
||||
|
||||
func TestCustomRegexTemplateParsingWithRotatedRanges(t *testing.T) {
|
||||
testYaml := `name: test
|
||||
keywords:
|
||||
- secret
|
||||
regex:
|
||||
token: ([a-zA-Z0-9]{32})
|
||||
verify:
|
||||
- endpoint: http://localhost:8000/
|
||||
unsafe: true
|
||||
headers:
|
||||
- 'Authorization: Bearer token'
|
||||
successRanges:
|
||||
- '200'
|
||||
rotatedRanges:
|
||||
- '401'
|
||||
- 403-404`
|
||||
|
||||
var got custom_detectorspb.CustomRegex
|
||||
assert.NoError(t, protoyaml.UnmarshalStrict([]byte(testYaml), &got))
|
||||
assert.Equal(t, 1, len(got.Verify))
|
||||
assert.Equal(t, []string{"200"}, got.Verify[0].SuccessRanges)
|
||||
assert.Equal(t, []string{"401", "403-404"}, got.Verify[0].RotatedRanges)
|
||||
}
|
||||
|
||||
func TestCustomRegexWebhookParsing(t *testing.T) {
|
||||
testCustomRegexWebhookYaml := `name: Internal bi tool
|
||||
keywords:
|
||||
@@ -738,6 +764,26 @@ func TestNewWebhookCustomRegex_Validation(t *testing.T) {
|
||||
wantErr: true,
|
||||
wantErrSubstr: `must contain a colon`,
|
||||
},
|
||||
{
|
||||
name: "ValidateVerifyRanges: invalid successRanges",
|
||||
mutate: func(pb *custom_detectorspb.CustomRegex) {
|
||||
pb.Verify = []*custom_detectorspb.VerifierConfig{
|
||||
{Endpoint: "https://example.com/verify", Headers: []string{"A: b"}, SuccessRanges: []string{"abc"}},
|
||||
}
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrSubstr: "unable to convert http code to int",
|
||||
},
|
||||
{
|
||||
name: "ValidateVerifyRanges: invalid rotatedRanges",
|
||||
mutate: func(pb *custom_detectorspb.CustomRegex) {
|
||||
pb.Verify = []*custom_detectorspb.VerifierConfig{
|
||||
{Endpoint: "https://example.com/verify", Headers: []string{"A: b"}, RotatedRanges: []string{"999"}},
|
||||
}
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrSubstr: "invalid http status code",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -779,6 +825,167 @@ func TestNewWebhookCustomRegex_EnsurePrimaryRegexNameSet(t *testing.T) {
|
||||
assert.Equal(t, "regex_a", detector.GetPrimaryRegexName(), "expected PrimaryRegexName to be set to regex_a")
|
||||
}
|
||||
|
||||
func TestVerificationWithConfigurableRanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
serverStatus int
|
||||
successRanges []string
|
||||
rotatedRanges []string
|
||||
wantVerified bool
|
||||
wantVerifyErr bool
|
||||
}{
|
||||
{
|
||||
name: "backward compat: no ranges, 200 -> verified",
|
||||
serverStatus: 200,
|
||||
wantVerified: true,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "backward compat: no ranges, 401 -> unverified",
|
||||
serverStatus: 401,
|
||||
wantVerified: false,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "successRanges match -> verified",
|
||||
serverStatus: 201,
|
||||
successRanges: []string{"200-202"},
|
||||
wantVerified: true,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "rotatedRanges match -> not verified, no error",
|
||||
serverStatus: 401,
|
||||
successRanges: []string{"200"},
|
||||
rotatedRanges: []string{"401", "403"},
|
||||
wantVerified: false,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "neither match -> not verified, verification error",
|
||||
serverStatus: 500,
|
||||
successRanges: []string{"200"},
|
||||
rotatedRanges: []string{"401"},
|
||||
wantVerified: false,
|
||||
wantVerifyErr: true,
|
||||
},
|
||||
{
|
||||
name: "successRanges range boundary inclusive",
|
||||
serverStatus: 250,
|
||||
successRanges: []string{"200-250"},
|
||||
wantVerified: true,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "only successRanges: non-match means rotated",
|
||||
serverStatus: 401,
|
||||
successRanges: []string{"200"},
|
||||
wantVerified: false,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "only rotatedRanges: non-match means live",
|
||||
serverStatus: 200,
|
||||
rotatedRanges: []string{"401", "403"},
|
||||
wantVerified: true,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
{
|
||||
name: "only rotatedRanges: match means rotated",
|
||||
serverStatus: 401,
|
||||
rotatedRanges: []string{"401"},
|
||||
wantVerified: false,
|
||||
wantVerifyErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(tt.serverStatus)
|
||||
_, _ = w.Write([]byte(`{"status":"ok"}`))
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
detector, err := NewWebhookCustomRegex(&custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"secret"},
|
||||
Regex: map[string]string{"token": `(secret_[a-zA-Z0-9]{10})`},
|
||||
Verify: []*custom_detectorspb.VerifierConfig{
|
||||
{
|
||||
Endpoint: ts.URL,
|
||||
Unsafe: true,
|
||||
Headers: []string{"Authorization: Bearer test"},
|
||||
SuccessRanges: tt.successRanges,
|
||||
RotatedRanges: tt.rotatedRanges,
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
results, err := detector.FromData(context.Background(), true, []byte("secret_ABCDEFGHIJ"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(results), "expected exactly one result")
|
||||
|
||||
result := results[0]
|
||||
assert.Equal(t, tt.wantVerified, result.Verified, "Verified mismatch")
|
||||
if tt.wantVerifyErr {
|
||||
assert.NotNil(t, result.VerificationError(), "expected a verification error")
|
||||
} else {
|
||||
assert.Nil(t, result.VerificationError(), "expected no verification error")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerificationMixedRangedAndLegacyVerifiers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Verifier 1 has ranges configured but returns a status matching neither.
|
||||
// Verifier 2 is legacy (no ranges) and returns 200.
|
||||
// The result should be Verified=true with NO verification error.
|
||||
tsRanged := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(500)
|
||||
}))
|
||||
defer tsRanged.Close()
|
||||
|
||||
tsLegacy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
_, _ = w.Write([]byte(`ok`))
|
||||
}))
|
||||
defer tsLegacy.Close()
|
||||
|
||||
detector, err := NewWebhookCustomRegex(&custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"secret"},
|
||||
Regex: map[string]string{"token": `(secret_[a-zA-Z0-9]{10})`},
|
||||
Verify: []*custom_detectorspb.VerifierConfig{
|
||||
{
|
||||
Endpoint: tsRanged.URL,
|
||||
Unsafe: true,
|
||||
Headers: []string{"A: b"},
|
||||
SuccessRanges: []string{"200"},
|
||||
RotatedRanges: []string{"401"},
|
||||
},
|
||||
{
|
||||
Endpoint: tsLegacy.URL,
|
||||
Unsafe: true,
|
||||
Headers: []string{"A: b"},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
results, err := detector.FromData(context.Background(), true, []byte("secret_ABCDEFGHIJ"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(results))
|
||||
assert.True(t, results[0].Verified, "expected Verified=true from legacy fallback")
|
||||
assert.Nil(t, results[0].VerificationError(), "legacy success must not produce a spurious verification error")
|
||||
}
|
||||
|
||||
func BenchmarkProductIndices(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = productIndices(3, 2, 6)
|
||||
|
||||
@@ -72,6 +72,28 @@ func ValidateVerifyHeaders(headers []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StatusCodeMatchesRanges reports whether code falls within any of the given
|
||||
// ranges. Each element is either a single HTTP status code ("200") or a
|
||||
// hyphenated inclusive range ("200-299"). Entries must have been pre-validated
|
||||
// by ValidateVerifyRanges; malformed entries are silently skipped.
|
||||
func StatusCodeMatchesRanges(code int, ranges []string) bool {
|
||||
for _, r := range ranges {
|
||||
if !strings.Contains(r, "-") {
|
||||
if c, err := strconv.Atoi(r); err == nil && c == code {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(r, "-", 2)
|
||||
lo, err1 := strconv.Atoi(parts[0])
|
||||
hi, err2 := strconv.Atoi(parts[1])
|
||||
if err1 == nil && err2 == nil && code >= lo && code <= hi {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ValidateVerifyRanges(ranges []string) error {
|
||||
const httpLowerRange = 100
|
||||
const httpUpperRange = 599
|
||||
|
||||
@@ -198,6 +198,90 @@ func TestCustomDetectorsVerifyRangeValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusCodeMatchesRanges(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
code int
|
||||
ranges []string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "single code match",
|
||||
code: 200,
|
||||
ranges: []string{"200"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "single code no match",
|
||||
code: 201,
|
||||
ranges: []string{"200"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "range lower bound",
|
||||
code: 200,
|
||||
ranges: []string{"200-250"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "range upper bound",
|
||||
code: 250,
|
||||
ranges: []string{"200-250"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "range middle",
|
||||
code: 225,
|
||||
ranges: []string{"200-250"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "range outside below",
|
||||
code: 199,
|
||||
ranges: []string{"200-250"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "range outside above",
|
||||
code: 251,
|
||||
ranges: []string{"200-250"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "multiple ranges first match",
|
||||
code: 200,
|
||||
ranges: []string{"200", "300-399"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "multiple ranges second match",
|
||||
code: 301,
|
||||
ranges: []string{"200", "300-399"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "multiple ranges no match",
|
||||
code: 500,
|
||||
ranges: []string{"200", "300-399"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "empty ranges",
|
||||
code: 200,
|
||||
ranges: nil,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := StatusCodeMatchesRanges(tt.code, tt.ranges)
|
||||
if got != tt.want {
|
||||
t.Errorf("StatusCodeMatchesRanges(%d, %v) = %v, want %v", tt.code, tt.ranges, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDetectorsVerifyRegexVarsValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -204,6 +204,7 @@ type VerifierConfig struct {
|
||||
Unsafe bool `protobuf:"varint,2,opt,name=unsafe,proto3" json:"unsafe,omitempty"`
|
||||
Headers []string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty"`
|
||||
SuccessRanges []string `protobuf:"bytes,4,rep,name=successRanges,proto3" json:"successRanges,omitempty"`
|
||||
RotatedRanges []string `protobuf:"bytes,5,rep,name=rotatedRanges,proto3" json:"rotatedRanges,omitempty"`
|
||||
}
|
||||
|
||||
func (x *VerifierConfig) Reset() {
|
||||
@@ -266,6 +267,13 @@ func (x *VerifierConfig) GetSuccessRanges() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *VerifierConfig) GetRotatedRanges() []string {
|
||||
if x != nil {
|
||||
return x.RotatedRanges
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ValidationConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -391,7 +399,7 @@ var file_custom_detectors_proto_rawDesc = []byte{
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x75, 0x73, 0x74,
|
||||
0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x56, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x0e, 0x56, 0x65, 0x72,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb4, 0x01, 0x0a, 0x0e, 0x56, 0x65, 0x72,
|
||||
0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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,
|
||||
@@ -400,25 +408,27 @@ var file_custom_detectors_proto_rawDesc = []byte{
|
||||
0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64,
|
||||
0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x61,
|
||||
0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x75, 0x63, 0x63,
|
||||
0x65, 0x73, 0x73, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x56, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25,
|
||||
0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x67, 0x69, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73,
|
||||
0x44, 0x69, 0x67, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x73, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x4c, 0x6f, 0x77, 0x65, 0x72,
|
||||
0x63, 0x61, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73,
|
||||
0x5f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x55, 0x70, 0x70, 0x65, 0x72, 0x63,
|
||||
0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f,
|
||||
0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x53, 0x70, 0x65, 0x63,
|
||||
0x69, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x72, 0x42, 0x44, 0x5a, 0x42, 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, 0x63, 0x75, 0x73, 0x74, 0x6f,
|
||||
0x6d, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x73, 0x73, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x6f, 0x74,
|
||||
0x61, 0x74, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x0d, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22,
|
||||
0xcb, 0x01, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73,
|
||||
0x5f, 0x64, 0x69, 0x67, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x44, 0x69, 0x67, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x73, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73,
|
||||
0x55, 0x70, 0x70, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x68,
|
||||
0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
|
||||
0x6e, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x72, 0x42, 0x44, 0x5a,
|
||||
0x42, 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, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||
0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -30,6 +30,7 @@ message VerifierConfig {
|
||||
bool unsafe = 2;
|
||||
repeated string headers = 3;
|
||||
repeated string successRanges = 4;
|
||||
repeated string rotatedRanges = 5;
|
||||
}
|
||||
|
||||
message ValidationConfig {
|
||||
|
||||
Reference in New Issue
Block a user