mirror of
https://github.com/trufflesecurity/trufflehog.git
synced 2026-05-16 13:20:35 +00:00
Added support for additional validation rules in custom detector (#4413)
* Added support for additional validation rules in custom detector * refactored the approach to support validations for each regex in config * resolved comments
This commit is contained in:
@@ -11,6 +11,10 @@ detectors:
|
||||
regex:
|
||||
secret: |-
|
||||
(?i)[\w.-]{0,50}?(?:access|auth|(?-i:[Aa]pi|API)|credential|creds|key|passw(?:or)?d|secret|token)(?:[ \t\w.-]{0,20})[\s'"]{0,3}(?:=|>|:{1,3}=|\|\||:|=>|\?=|,)[\x60'"\s=]{0,5}([\w.=-]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3})(?:[\x60'"\s;]|\\[nr]|$)
|
||||
validations:
|
||||
secret: # name of the regex to apply these validations to
|
||||
contains_digit: true
|
||||
contains_special_char: true
|
||||
entropy: 3.5
|
||||
# exclude_regexes_capture:
|
||||
# - |-
|
||||
|
||||
@@ -43,6 +43,13 @@ This guide will walk you through setting up a custom detector in TruffleHog to i
|
||||
- **`exclude_regexes_match`**: This parameter enables you to define regex patterns to exclude entire matches from being reported as secrets. This applies to the entire matched string, not just the token.
|
||||
- **`entropy`**: This parameter is used to assess the randomness of detected strings. High entropy often indicates that a string is a potential secret, such as an API key or password, due to its complexity and unpredictability. It helps in filtering false-positives. While an entropy threshold of `3` can be a starting point, it's essential to adjust this value based on your project's specific requirements and the nature of the data you have.
|
||||
- **`exclude_words`**: This parameter allows you to specify a list of words that, if present in a detected string, will cause TruffleHog to ignore that string. This is a substring match and does not enforce word boundaries. It applies only to the token.
|
||||
- **`validations`**: This parameter lets you define extra validation rules for each regex specified in the regex option. These rules address limitations of Go's RE2 engine, such as the lack of lookahead support, and are applied after a regex match to help reduce false positives.
|
||||
Available validation options:
|
||||
- **`contains_digit`**: Ensures the match contains at least one numeric digit (0-9). Useful for API keys or tokens that must include numbers.
|
||||
- **`contains_lowercase`**: Ensures the match contains at least one lowercase letter (a-z). Common requirement for passwords and mixed-case tokens.
|
||||
- **`contains_uppercase`**: Ensures the match contains at least one uppercase letter (A-Z). Helps validate tokens that follow mixed-case conventions.
|
||||
- **`contains_special_char`**: Ensures the match contains at least one special character from the set `!@#$%^&*()_+-=[]{}|;:,.<>?`. Useful for complex passwords or encoded tokens.
|
||||
|
||||
|
||||
[Here](/examples/generic_with_filters.yml) is an example of a custom detector using these parameters.
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ func (c *CustomRegexWebhook) FromData(ctx context.Context, verify bool, data []b
|
||||
|
||||
MatchLoop:
|
||||
for _, match := range matches {
|
||||
for _, values := range match {
|
||||
for key, values := range match {
|
||||
// attempt to use capture group
|
||||
secret := values[0]
|
||||
if len(values) > 1 {
|
||||
@@ -150,6 +150,26 @@ MatchLoop:
|
||||
continue MatchLoop
|
||||
}
|
||||
}
|
||||
|
||||
if validations := c.GetValidations(); validations != nil {
|
||||
validationRules := []struct {
|
||||
enabled bool
|
||||
validator func(string) bool
|
||||
}{
|
||||
{validations[key].GetContainsDigit(), ContainsDigit},
|
||||
{validations[key].GetContainsLowercase(), ContainsLowercase},
|
||||
{validations[key].GetContainsUppercase(), ContainsUppercase},
|
||||
{validations[key].GetContainsSpecialChar(), ContainsSpecialChar},
|
||||
}
|
||||
|
||||
for _, rule := range validationRules {
|
||||
if rule.enabled && !rule.validator(secret) {
|
||||
// skip this match if a validation rule is enabled but missing from the secret
|
||||
continue MatchLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g.Go(func() error {
|
||||
|
||||
@@ -4,9 +4,13 @@ import (
|
||||
"context"
|
||||
"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/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/custom_detectorspb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/protoyaml"
|
||||
)
|
||||
|
||||
@@ -227,6 +231,334 @@ func TestDetectorPrimarySecret(t *testing.T) {
|
||||
assert.Equal(t, "secret_YI7C90ACY1_yy", results[0].GetPrimarySecretValue())
|
||||
}
|
||||
|
||||
func TestDetectorValidations(t *testing.T) {
|
||||
type args struct {
|
||||
CustomRegex *custom_detectorspb.CustomRegex
|
||||
Data string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input args
|
||||
want []detectors.Result
|
||||
}{
|
||||
{
|
||||
name: "custom validation - contains digit",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsDigit: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStr0ngP@ssword!
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStr0ngP@ssword!"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - does not contains digit",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsDigit: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongPassword!
|
||||
End of file`,
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "custom validation - contains lowercase",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsLowercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongPassword!
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStrongPassword!"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - does not contains lowercase",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsLowercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MYSTRONGPASSWORD!
|
||||
End of file`,
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "custom validation - contains uppercase",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsUppercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongPassword!
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStrongPassword!"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - does not contains uppercase",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsUppercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: mystrongpassword!
|
||||
End of file`,
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "custom validation - contains special character",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStr@ngP@ssword!
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStr@ngP@ssword!"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - does not contains special character",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongPassword
|
||||
End of file`,
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "custom validation - contains uppercase and special characters",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsUppercase: true,
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongP@ssword
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStrongP@ssword"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - contains uppercase but does not contain special characters",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsUppercase: true,
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongPassword
|
||||
End of file`,
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "custom validation - wrong regex name in validations",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"wrong": {
|
||||
ContainsUppercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: mystrongp@ssword
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("mystrongp@ssword"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom validation - multiple regex validations",
|
||||
input: args{
|
||||
CustomRegex: &custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
Keywords: []string{"password", "api_key"},
|
||||
Regex: map[string]string{
|
||||
"password": `([A-Za-z0-9!@#$%^&*()_+=\-]{12,})`,
|
||||
"api_key": `([a-f0-9_-]{32})`,
|
||||
},
|
||||
Validations: map[string]*custom_detectorspb.ValidationConfig{
|
||||
"password": {
|
||||
ContainsUppercase: true,
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
"api_key": {
|
||||
ContainsSpecialChar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: `This is custom example
|
||||
This file has a random text and maybe a secret
|
||||
Password: MyStrongP@ssword
|
||||
API_Key: c392c9837d69b44c764cbf260b-e6184 // should be detected
|
||||
API_Key: c392c9837d69b44c764cbf260be6184 // should be filtered by validation
|
||||
End of file`,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: "test",
|
||||
Verified: false,
|
||||
Raw: []byte("MyStrongP@sswordc392c9837d69b44c764cbf260b-e6184"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
detector, err := NewWebhookCustomRegex(tt.input.CustomRegex)
|
||||
assert.NoError(t, err)
|
||||
results, err := detector.FromData(context.Background(), false, []byte(tt.input.Data))
|
||||
assert.NoError(t, err)
|
||||
|
||||
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "ExtraData", "verificationError", "primarySecret")
|
||||
if diff := cmp.Diff(results, tt.want, ignoreOpts); diff != "" {
|
||||
t.Errorf("CustomDetector.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkProductIndices(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = productIndices(3, 2, 6)
|
||||
|
||||
@@ -107,3 +107,47 @@ func ValidateRegexVars(regex map[string]string, body ...string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// === Custom Validations ===
|
||||
|
||||
// ContainsDigit checks if string contains at least one digit
|
||||
func ContainsDigit(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
char := s[i]
|
||||
if char >= '0' && char <= '9' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsLowercase checks if string contains at least one lowercase letter
|
||||
func ContainsLowercase(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
char := s[i]
|
||||
if char >= 'a' && char <= 'z' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsUppercase checks if string contains at least one uppercase letter
|
||||
func ContainsUppercase(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
char := s[i]
|
||||
if char >= 'A' && char <= 'Z' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsSpecialChar checks if string contains at least one special character
|
||||
func ContainsSpecialChar(s string) bool {
|
||||
specialChars := "!@#$%^&*()_+-=[]{}|;:,.<>?"
|
||||
return strings.ContainsAny(s, specialChars)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package custom_detectors
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCustomDetectorsKeywordValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -232,3 +234,119 @@ func TestCustomDetectorsVerifyRegexVarsValidation(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainsDigit(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "contains digit",
|
||||
args: args{s: "lzscqf&60M"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "does not contains digit",
|
||||
args: args{s: "ZlDQOdaM*vsT"},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ContainsDigit(tt.args.s); got != tt.want {
|
||||
t.Errorf("ContainsDigit() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainsLowercase(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "contains lower case",
|
||||
args: args{s: "g0AJBHdnhRG2"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "does not contains lower case",
|
||||
args: args{s: "V7T#MEA6@+TN"},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ContainsLowercase(tt.args.s); got != tt.want {
|
||||
t.Errorf("ContainsDigit() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainsUppercase(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "contains upper case",
|
||||
args: args{s: "G1sKkJeKlSQf"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "does not contains upper case",
|
||||
args: args{s: "pq6-14ydz1@d"},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ContainsUppercase(tt.args.s); got != tt.want {
|
||||
t.Errorf("ContainsDigit() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainsSpecialChar(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "contains upper case",
|
||||
args: args{s: "HP$gE7s=do0B"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "does not contains upper case",
|
||||
args: args{s: "w9gvBYctrSjB"},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ContainsSpecialChar(tt.args.s); got != tt.want {
|
||||
t.Errorf("ContainsDigit() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,16 +73,17 @@ type CustomRegex struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Keywords []string `protobuf:"bytes,2,rep,name=keywords,proto3" json:"keywords,omitempty"`
|
||||
Regex map[string]string `protobuf:"bytes,3,rep,name=regex,proto3" json:"regex,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
Verify []*VerifierConfig `protobuf:"bytes,4,rep,name=verify,proto3" json:"verify,omitempty"`
|
||||
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
|
||||
ExcludeRegexesCapture []string `protobuf:"bytes,6,rep,name=exclude_regexes_capture,json=excludeRegexesCapture,proto3" json:"exclude_regexes_capture,omitempty"`
|
||||
ExcludeWords []string `protobuf:"bytes,7,rep,name=exclude_words,json=excludeWords,proto3" json:"exclude_words,omitempty"`
|
||||
Entropy float32 `protobuf:"fixed32,8,opt,name=entropy,proto3" json:"entropy,omitempty"`
|
||||
ExcludeRegexesMatch []string `protobuf:"bytes,9,rep,name=exclude_regexes_match,json=excludeRegexesMatch,proto3" json:"exclude_regexes_match,omitempty"`
|
||||
PrimaryRegexName string `protobuf:"bytes,10,opt,name=primary_regex_name,json=primaryRegexName,proto3" json:"primary_regex_name,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Keywords []string `protobuf:"bytes,2,rep,name=keywords,proto3" json:"keywords,omitempty"`
|
||||
Regex map[string]string `protobuf:"bytes,3,rep,name=regex,proto3" json:"regex,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
Verify []*VerifierConfig `protobuf:"bytes,4,rep,name=verify,proto3" json:"verify,omitempty"`
|
||||
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
|
||||
ExcludeRegexesCapture []string `protobuf:"bytes,6,rep,name=exclude_regexes_capture,json=excludeRegexesCapture,proto3" json:"exclude_regexes_capture,omitempty"`
|
||||
ExcludeWords []string `protobuf:"bytes,7,rep,name=exclude_words,json=excludeWords,proto3" json:"exclude_words,omitempty"`
|
||||
Entropy float32 `protobuf:"fixed32,8,opt,name=entropy,proto3" json:"entropy,omitempty"`
|
||||
ExcludeRegexesMatch []string `protobuf:"bytes,9,rep,name=exclude_regexes_match,json=excludeRegexesMatch,proto3" json:"exclude_regexes_match,omitempty"`
|
||||
PrimaryRegexName string `protobuf:"bytes,10,opt,name=primary_regex_name,json=primaryRegexName,proto3" json:"primary_regex_name,omitempty"`
|
||||
Validations map[string]*ValidationConfig `protobuf:"bytes,11,rep,name=validations,proto3" json:"validations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (x *CustomRegex) Reset() {
|
||||
@@ -187,6 +188,13 @@ func (x *CustomRegex) GetPrimaryRegexName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CustomRegex) GetValidations() map[string]*ValidationConfig {
|
||||
if x != nil {
|
||||
return x.Validations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VerifierConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -258,6 +266,77 @@ func (x *VerifierConfig) GetSuccessRanges() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ValidationConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ContainsDigit bool `protobuf:"varint,1,opt,name=contains_digit,json=containsDigit,proto3" json:"contains_digit,omitempty"`
|
||||
ContainsLowercase bool `protobuf:"varint,2,opt,name=contains_lowercase,json=containsLowercase,proto3" json:"contains_lowercase,omitempty"`
|
||||
ContainsUppercase bool `protobuf:"varint,3,opt,name=contains_uppercase,json=containsUppercase,proto3" json:"contains_uppercase,omitempty"`
|
||||
ContainsSpecialChar bool `protobuf:"varint,4,opt,name=contains_special_char,json=containsSpecialChar,proto3" json:"contains_special_char,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) Reset() {
|
||||
*x = ValidationConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_custom_detectors_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ValidationConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ValidationConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_custom_detectors_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ValidationConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ValidationConfig) Descriptor() ([]byte, []int) {
|
||||
return file_custom_detectors_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) GetContainsDigit() bool {
|
||||
if x != nil {
|
||||
return x.ContainsDigit
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) GetContainsLowercase() bool {
|
||||
if x != nil {
|
||||
return x.ContainsLowercase
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) GetContainsUppercase() bool {
|
||||
if x != nil {
|
||||
return x.ContainsUppercase
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ValidationConfig) GetContainsSpecialChar() bool {
|
||||
if x != nil {
|
||||
return x.ContainsSpecialChar
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_custom_detectors_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_custom_detectors_proto_rawDesc = []byte{
|
||||
@@ -270,7 +349,7 @@ var file_custom_detectors_proto_rawDesc = []byte{
|
||||
0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x75, 0x73, 0x74,
|
||||
0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x43, 0x75, 0x73,
|
||||
0x74, 0x6f, 0x6d, 0x52, 0x65, 0x67, 0x65, 0x78, 0x52, 0x09, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x73, 0x22, 0xec, 0x03, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65,
|
||||
0x6f, 0x72, 0x73, 0x22, 0xa2, 0x05, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65,
|
||||
0x67, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77, 0x6f,
|
||||
@@ -297,25 +376,49 @@ var file_custom_detectors_proto_rawDesc = []byte{
|
||||
0x67, 0x65, 0x78, 0x65, 0x73, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72,
|
||||
0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52,
|
||||
0x65, 0x67, 0x65, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x38, 0x0a, 0x0a, 0x52, 0x65, 0x67, 0x65,
|
||||
0x78, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||
0x38, 0x01, 0x22, 0x8e, 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, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75,
|
||||
0x6e, 0x73, 0x61, 0x66, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x6e, 0x73,
|
||||
0x61, 0x66, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x61, 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, 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, 0x67, 0x65, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e,
|
||||
0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73,
|
||||
0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x67, 0x65, 0x78, 0x2e, 0x56, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x52, 0x65,
|
||||
0x67, 0x65, 0x78, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x1a, 0x62, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x05, 0x76, 0x61,
|
||||
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,
|
||||
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,
|
||||
0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x06, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x61,
|
||||
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,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -330,22 +433,26 @@ func file_custom_detectors_proto_rawDescGZIP() []byte {
|
||||
return file_custom_detectors_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_custom_detectors_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_custom_detectors_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_custom_detectors_proto_goTypes = []interface{}{
|
||||
(*CustomDetectors)(nil), // 0: custom_detectors.CustomDetectors
|
||||
(*CustomRegex)(nil), // 1: custom_detectors.CustomRegex
|
||||
(*VerifierConfig)(nil), // 2: custom_detectors.VerifierConfig
|
||||
nil, // 3: custom_detectors.CustomRegex.RegexEntry
|
||||
(*CustomDetectors)(nil), // 0: custom_detectors.CustomDetectors
|
||||
(*CustomRegex)(nil), // 1: custom_detectors.CustomRegex
|
||||
(*VerifierConfig)(nil), // 2: custom_detectors.VerifierConfig
|
||||
(*ValidationConfig)(nil), // 3: custom_detectors.ValidationConfig
|
||||
nil, // 4: custom_detectors.CustomRegex.RegexEntry
|
||||
nil, // 5: custom_detectors.CustomRegex.ValidationsEntry
|
||||
}
|
||||
var file_custom_detectors_proto_depIdxs = []int32{
|
||||
1, // 0: custom_detectors.CustomDetectors.detectors:type_name -> custom_detectors.CustomRegex
|
||||
3, // 1: custom_detectors.CustomRegex.regex:type_name -> custom_detectors.CustomRegex.RegexEntry
|
||||
4, // 1: custom_detectors.CustomRegex.regex:type_name -> custom_detectors.CustomRegex.RegexEntry
|
||||
2, // 2: custom_detectors.CustomRegex.verify:type_name -> custom_detectors.VerifierConfig
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
5, // 3: custom_detectors.CustomRegex.validations:type_name -> custom_detectors.CustomRegex.ValidationsEntry
|
||||
3, // 4: custom_detectors.CustomRegex.ValidationsEntry.value:type_name -> custom_detectors.ValidationConfig
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_custom_detectors_proto_init() }
|
||||
@@ -390,6 +497,18 @@ func file_custom_detectors_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_custom_detectors_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ValidationConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@@ -397,7 +516,7 @@ func file_custom_detectors_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_custom_detectors_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -235,6 +235,52 @@ func (m *CustomRegex) validate(all bool) error {
|
||||
|
||||
// no validation rules for PrimaryRegexName
|
||||
|
||||
{
|
||||
sorted_keys := make([]string, len(m.GetValidations()))
|
||||
i := 0
|
||||
for key := range m.GetValidations() {
|
||||
sorted_keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] })
|
||||
for _, key := range sorted_keys {
|
||||
val := m.GetValidations()[key]
|
||||
_ = val
|
||||
|
||||
// no validation rules for Validations[key]
|
||||
|
||||
if all {
|
||||
switch v := interface{}(val).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, CustomRegexValidationError{
|
||||
field: fmt.Sprintf("Validations[%v]", key),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, CustomRegexValidationError{
|
||||
field: fmt.Sprintf("Validations[%v]", key),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(val).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return CustomRegexValidationError{
|
||||
field: fmt.Sprintf("Validations[%v]", key),
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return CustomRegexMultiError(errors)
|
||||
}
|
||||
@@ -425,3 +471,111 @@ var _ interface {
|
||||
Cause() error
|
||||
ErrorName() string
|
||||
} = VerifierConfigValidationError{}
|
||||
|
||||
// Validate checks the field values on ValidationConfig with the rules defined
|
||||
// in the proto definition for this message. If any rules are violated, the
|
||||
// first error encountered is returned, or nil if there are no violations.
|
||||
func (m *ValidationConfig) Validate() error {
|
||||
return m.validate(false)
|
||||
}
|
||||
|
||||
// ValidateAll checks the field values on ValidationConfig with the rules
|
||||
// defined in the proto definition for this message. If any rules are
|
||||
// violated, the result is a list of violation errors wrapped in
|
||||
// ValidationConfigMultiError, or nil if none found.
|
||||
func (m *ValidationConfig) ValidateAll() error {
|
||||
return m.validate(true)
|
||||
}
|
||||
|
||||
func (m *ValidationConfig) validate(all bool) error {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errors []error
|
||||
|
||||
// no validation rules for ContainsDigit
|
||||
|
||||
// no validation rules for ContainsLowercase
|
||||
|
||||
// no validation rules for ContainsUppercase
|
||||
|
||||
// no validation rules for ContainsSpecialChar
|
||||
|
||||
if len(errors) > 0 {
|
||||
return ValidationConfigMultiError(errors)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidationConfigMultiError is an error wrapping multiple validation errors
|
||||
// returned by ValidationConfig.ValidateAll() if the designated constraints
|
||||
// aren't met.
|
||||
type ValidationConfigMultiError []error
|
||||
|
||||
// Error returns a concatenation of all the error messages it wraps.
|
||||
func (m ValidationConfigMultiError) Error() string {
|
||||
var msgs []string
|
||||
for _, err := range m {
|
||||
msgs = append(msgs, err.Error())
|
||||
}
|
||||
return strings.Join(msgs, "; ")
|
||||
}
|
||||
|
||||
// AllErrors returns a list of validation violation errors.
|
||||
func (m ValidationConfigMultiError) AllErrors() []error { return m }
|
||||
|
||||
// ValidationConfigValidationError is the validation error returned by
|
||||
// ValidationConfig.Validate if the designated constraints aren't met.
|
||||
type ValidationConfigValidationError struct {
|
||||
field string
|
||||
reason string
|
||||
cause error
|
||||
key bool
|
||||
}
|
||||
|
||||
// Field function returns field value.
|
||||
func (e ValidationConfigValidationError) Field() string { return e.field }
|
||||
|
||||
// Reason function returns reason value.
|
||||
func (e ValidationConfigValidationError) Reason() string { return e.reason }
|
||||
|
||||
// Cause function returns cause value.
|
||||
func (e ValidationConfigValidationError) Cause() error { return e.cause }
|
||||
|
||||
// Key function returns key value.
|
||||
func (e ValidationConfigValidationError) Key() bool { return e.key }
|
||||
|
||||
// ErrorName returns error name.
|
||||
func (e ValidationConfigValidationError) ErrorName() string { return "ValidationConfigValidationError" }
|
||||
|
||||
// Error satisfies the builtin error interface
|
||||
func (e ValidationConfigValidationError) Error() string {
|
||||
cause := ""
|
||||
if e.cause != nil {
|
||||
cause = fmt.Sprintf(" | caused by: %v", e.cause)
|
||||
}
|
||||
|
||||
key := ""
|
||||
if e.key {
|
||||
key = "key for "
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"invalid %sValidationConfig.%s: %s%s",
|
||||
key,
|
||||
e.field,
|
||||
e.reason,
|
||||
cause)
|
||||
}
|
||||
|
||||
var _ error = ValidationConfigValidationError{}
|
||||
|
||||
var _ interface {
|
||||
Field() string
|
||||
Reason() string
|
||||
Key() bool
|
||||
Cause() error
|
||||
ErrorName() string
|
||||
} = ValidationConfigValidationError{}
|
||||
|
||||
@@ -21,6 +21,7 @@ message CustomRegex {
|
||||
float entropy = 8;
|
||||
repeated string exclude_regexes_match = 9;
|
||||
string primary_regex_name = 10;
|
||||
map<string, ValidationConfig> validations = 11;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,3 +31,10 @@ message VerifierConfig {
|
||||
repeated string headers = 3;
|
||||
repeated string successRanges = 4;
|
||||
}
|
||||
|
||||
message ValidationConfig {
|
||||
bool contains_digit = 1;
|
||||
bool contains_lowercase = 2;
|
||||
bool contains_uppercase = 3;
|
||||
bool contains_special_char = 4;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user