diff --git a/go.mod b/go.mod index de595483fefb..a995b4ab4258 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/getsentry/sentry-go v0.15.0 github.com/go-errors/errors v1.4.2 github.com/go-git/go-git/v5 v5.4.2 + github.com/go-ldap/ldap/v3 v3.4.4 github.com/go-logr/logr v1.2.3 github.com/go-logr/zapr v1.2.3 github.com/go-redis/redis v6.15.9+incompatible @@ -73,6 +74,7 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect github.com/Microsoft/go-winio v0.4.16 // indirect github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect @@ -84,6 +86,7 @@ require ( github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dsnet/compress v0.0.1 // indirect github.com/emirpasic/gods v1.12.0 // 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/go-billy/v5 v5.3.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect diff --git a/go.sum b/go.sum index 393f88684d31..45b957643134 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft7pkxDf6WoUvEZJ/uOKsvtpjLnn8MU= +github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -144,6 +146,8 @@ github.com/getsentry/sentry-go v0.15.0 h1:CP9bmA7pralrVUedYZsmIHWpq/pBtXTSew7xvV github.com/getsentry/sentry-go v0.15.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2HtRckJk9XVxJ9I= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= +github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= @@ -158,6 +162,8 @@ github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -403,6 +409,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= diff --git a/pkg/detectors/ldap/ldap.go b/pkg/detectors/ldap/ldap.go new file mode 100644 index 000000000000..fa59fa4db225 --- /dev/null +++ b/pkg/detectors/ldap/ldap.go @@ -0,0 +1,144 @@ +package ldap + +import ( + "context" + "crypto/tls" + "net/url" + "regexp" + "strings" + "time" + + "github.com/go-ldap/ldap/v3" + "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 ( + // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. + uriPat = regexp.MustCompile(`\b(?i)ldaps?://[\S]+\b`) + // ldap://127.0.0.1:389 + // ldap://127.0.0.1 + // ldap://mydomain.test + // ldaps://[fe80:4049:92ff:fe44:4bd1]:5060 + // ldap://[fe80::4bd1]:5060 + // ldap://ds.example.com:389/dc=example,dc=com?givenName,sn,cn?sub?(uid=john.doe) + usernamePat = regexp.MustCompile(detectors.PrefixRegex([]string{"user", "bind"}) + `["']([a-zA-Z=,]{4,150})["']`) + passwordPat = regexp.MustCompile(detectors.PrefixRegex([]string{"pass"}) + `["']([\S]{4,48})["']`) + + // https://learn.microsoft.com/en-us/windows/win32/api/iads/nf-iads-iadsopendsobject-opendsobject?redirectedfrom=MSDN + // I.E. Set ou = dso.OpenDSObject("LDAP://DC.business.com/OU=IT,DC=Business,DC=com", "Business\administrator", "Pa$$word01", 1) + iadPat = regexp.MustCompile(`OpenDSObject\(\"(?i)(ldaps?://[\S]+)\", ?\"([\S]+)\", ?\"([\S]+)\",[ \d]+\)`) +) + +// 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{"ldaps://", "ldap://"} +} + +// FromData will find and optionally verify Ldap 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) + + // Check for matches in the URI + username + password format + uriMatches := uriPat.FindAllString(dataStr, -1) + for _, uri := range uriMatches { + ldapURL, err := url.Parse(uri) + if err != nil { + continue + } + + usernameMatches := usernamePat.FindAllStringSubmatch(dataStr, -1) + for _, username := range usernameMatches { + passwordMatches := passwordPat.FindAllStringSubmatch(dataStr, -1) + for _, password := range passwordMatches { + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_LDAP, + Raw: []byte(strings.Join([]string{ldapURL.String(), username[1], password[1]}, "\t")), + } + + if verify { + s1.Verified = verifyLDAP(ctx, username[1], password[1], ldapURL) + } + + results = append(results, s1) + } + } + } + + // Check for matches for the IAD library format + iadMatches := iadPat.FindAllStringSubmatch(dataStr, -1) + for _, iad := range iadMatches { + uri := iad[1] + username := iad[2] + password := iad[3] + + ldapURL, err := url.Parse(uri) + if err != nil { + continue + } + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_LDAP, + Raw: []byte(strings.Join([]string{ldapURL.String(), username, password}, "\t")), + } + + if verify { + s1.Verified = verifyLDAP(ctx, username, password, ldapURL) + } + + results = append(results, s1) + } + + return results, nil +} + +func verifyLDAP(ctx context.Context, username, password string, ldapURL *url.URL) bool { + // Tests with non-TLS, TLS, and STARTTLS + + ldap.DefaultTimeout = 5 * time.Second + + uri := ldapURL.String() + + switch ldapURL.Scheme { + case "ldap": + // Non-TLS dial + l, err := ldap.DialURL(uri) + if err == nil { + defer l.Close() + // Non-TLS verify + err = l.Bind(username, password) + if err == nil { + return true + } + + // STARTTLS + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err == nil { + // STARTTLS verify + err = l.Bind(username, password) + if err == nil { + return true + } + } + } + case "ldaps": + // TLS dial + l, err := ldap.DialTLS("tcp", uri, &tls.Config{InsecureSkipVerify: true}) + if err == nil { + defer l.Close() + // TLS verify + err = l.Bind(username, password) + if err == nil { + return true + } + } + } + + return false +} diff --git a/pkg/detectors/ldap/ldap_integration_test.go b/pkg/detectors/ldap/ldap_integration_test.go new file mode 100644 index 000000000000..3c7a2779ef6f --- /dev/null +++ b/pkg/detectors/ldap/ldap_integration_test.go @@ -0,0 +1,214 @@ +//go:build detectors && integration +// +build detectors,integration + +package ldap + +import ( + "bytes" + "context" + "errors" + "os" + "os/exec" + "strings" + "testing" + "time" + + "github.com/kylelemons/godebug/pretty" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestMain(m *testing.M) { + code, err := runMain(m) + if err != nil { + panic(err) + } + os.Exit(code) +} + +func runMain(m *testing.M) (int, error) { + if err := startOpenLDAP(); err != nil { + return 0, err + } + defer stopOpenLDAP() + return m.Run(), nil +} + +func dockerLogLine(hash string, needle string) chan struct{} { + ch := make(chan struct{}, 1) + go func() { + for { + out, err := exec.Command("docker", "logs", hash).CombinedOutput() + if err != nil { + panic(err) + } + if strings.Contains(string(out), needle) { + ch <- struct{}{} + return + } + time.Sleep(1 * time.Second) + } + }() + return ch +} + +func TestLdap_Integration_FromChunk(t *testing.T) { + 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 with URI and separate user+password usage, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(` + ldap://localhost:1389 + binddn="cn=admin,dc=example,dc=org" + pass="P@55w0rd"`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + Verified: true, + }, + }, + wantErr: false, + }, + { + name: "found with URI and separate user+password usage, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(` + ldap://localhost:1389 + binddn="cn=someuser,dc=example,dc=org" + pass="P@55w0rd"`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + Verified: false, + }, + }, + wantErr: false, + }, + { + name: "found with IAD lib usage, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(`Set ou = dso.OpenDSObject("LDAP://localhost:1389", "cn=admin,dc=example,dc=org", "P@55w0rd", 1)`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + Verified: true, + }, + }, + wantErr: false, + }, + { + name: "found with IAD lib usage, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(`Set ou = dso.OpenDSObject("LDAP://localhost:1389", "cn=admin,dc=example,dc=org", "P@55w0rd", 1)`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + Verified: true, + }, + }, + wantErr: false, + }, + { + name: "found with IAD lib usage, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(`Set ou = dso.OpenDSObject("LDAP://localhost:1389", "cn=admin,dc=example,dc=org", "invalid", 1)`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + 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("Ldap.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("Ldap.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + } + }) + } +} + +var containerID string + +func startOpenLDAP() error { + cmd := exec.Command( + "docker", "run", "--rm", "-p", "1389:1389", + "-e", "LDAP_ROOT=dc=example,dc=org", + "-e", "LDAP_ADMIN_USERNAME=admin", + "-e", "LDAP_ADMIN_PASSWORD=P@55w0rd", + "-d", "bitnami/openldap:latest", + ) + out, err := cmd.Output() + if err != nil { + return err + } + containerID = string(bytes.TrimSpace(out)) + select { + case <-dockerLogLine(containerID, "slapd starting"): + return nil + case <-time.After(30 * time.Second): + stopOpenLDAP() + return errors.New("timeout waiting for postgres database to be ready") + } +} + +func stopOpenLDAP() { + exec.Command("docker", "kill", containerID).Run() +} diff --git a/pkg/detectors/ldap/ldap_test.go b/pkg/detectors/ldap/ldap_test.go new file mode 100644 index 000000000000..f054c722f1f9 --- /dev/null +++ b/pkg/detectors/ldap/ldap_test.go @@ -0,0 +1,91 @@ +//go:build detectors +// +build detectors + +package ldap + +import ( + "context" + "testing" + + "github.com/kylelemons/godebug/pretty" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestLdap_FromChunk(t *testing.T) { + 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 with IAD lib usage, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(`Set ou = dso.OpenDSObject("LDAP://DC.business.com/OU=IT,DC=Business,DC=com", "Business\administrator", "Pa$$word01", 1)`), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_LDAP, + 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("Ldap.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("Ldap.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) + } + } + }) + } +} diff --git a/pkg/engine/defaults.go b/pkg/engine/defaults.go index 9cb901bf80fd..10a4c6f9fcf3 100644 --- a/pkg/engine/defaults.go +++ b/pkg/engine/defaults.go @@ -350,6 +350,7 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/languagelayer" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/lastfm" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/launchdarkly" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/ldap" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/leadfeeder" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/lemlist" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/lendflow" @@ -1489,6 +1490,7 @@ func DefaultDetectors() []detectors.Detector { sqlserver.Scanner{}, redis.Scanner{}, ftp.Scanner{}, + ldap.Scanner{}, shopify.Scanner{}, } } diff --git a/pkg/pb/detectorspb/detectors.pb.go b/pkg/pb/detectorspb/detectors.pb.go index f300db7eca4d..74274a0156c6 100644 --- a/pkg/pb/detectorspb/detectors.pb.go +++ b/pkg/pb/detectorspb/detectors.pb.go @@ -969,6 +969,7 @@ const ( DetectorType_SQLServer DetectorType = 898 DetectorType_FTP DetectorType = 899 DetectorType_Redis DetectorType = 900 + DetectorType_LDAP DetectorType = 901 DetectorType_Shopify DetectorType = 902 ) @@ -1872,6 +1873,7 @@ var ( 898: "SQLServer", 899: "FTP", 900: "Redis", + 901: "LDAP", 902: "Shopify", } DetectorType_value = map[string]int32{ @@ -2772,6 +2774,7 @@ var ( "SQLServer": 898, "FTP": 899, "Redis": 900, + "LDAP": 901, "Shopify": 902, } ) @@ -3137,7 +3140,7 @@ var file_detectors_proto_rawDesc = []byte{ 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, 0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x41, 0x53, 0x45, 0x36, 0x34, 0x10, - 0x02, 0x2a, 0xe5, 0x70, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79, + 0x02, 0x2a, 0xf0, 0x70, 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, 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, @@ -4038,12 +4041,13 @@ var file_detectors_proto_rawDesc = []byte{ 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x56, 0x32, 0x10, 0x81, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x51, 0x4c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x10, 0x82, 0x07, 0x12, 0x08, 0x0a, 0x03, 0x46, 0x54, 0x50, 0x10, 0x83, 0x07, 0x12, - 0x0a, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x10, 0x84, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x53, - 0x68, 0x6f, 0x70, 0x69, 0x66, 0x79, 0x10, 0x86, 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, + 0x0a, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x10, 0x84, 0x07, 0x12, 0x09, 0x0a, 0x04, 0x4c, + 0x44, 0x41, 0x50, 0x10, 0x85, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x6f, 0x70, 0x69, 0x66, + 0x79, 0x10, 0x86, 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 ( diff --git a/proto/detectors.proto b/proto/detectors.proto index 313c3aec1e15..8b639dbb0691 100644 --- a/proto/detectors.proto +++ b/proto/detectors.proto @@ -908,6 +908,7 @@ enum DetectorType { SQLServer = 898; FTP = 899; Redis = 900; + LDAP = 901; Shopify = 902; }