Skip to content

Commit 8c649ff

Browse files
committed
add confluent API key detection in V2 detector
1 parent f5550ff commit 8c649ff

File tree

4 files changed

+38
-35
lines changed

4 files changed

+38
-35
lines changed

pkg/detectors/confluent/v1/confluent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (s Scanner) Keywords() []string {
3535
return []string{"confluent"}
3636
}
3737

38-
func (Scanner) Version() int { return 1 }
38+
func (s Scanner) Version() int { return 1 }
3939

4040
// FromData will find and optionally verify Confluent secrets in a given set of bytes.
4141
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {

pkg/detectors/confluent/v2/confluent.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ type Scanner struct {
2121
var _ detectors.Detector = (*Scanner)(nil)
2222

2323
var (
24+
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"confluent"}) + `\b([a-zA-Z0-9]{16})\b`)
2425
// Match cflt prefix followed by 60 characters consisting of A-Z, a-z, 0-9, + or /
2526
//See https://docs.confluent.io/cloud/current/security/authenticate/workload-identities/service-accounts/api-keys/overview.html#api-secret-format
26-
secretPat = regexp.MustCompile(detectors.PrefixRegex([]string{"Confluent"}) + `\b(cflt[A-Za-z0-9+/]{60})\b`)
27+
secretPat = regexp.MustCompile(`\b(cflt[A-Za-z0-9+/]{60})\b`)
2728
)
2829

2930
// Keywords are used for efficiently pre-filtering chunks.
@@ -32,31 +33,37 @@ func (s Scanner) Keywords() []string {
3233
return []string{"cflt"}
3334
}
3435

35-
func (Scanner) Version() int { return 2 }
36+
func (s Scanner) Version() int { return 2 }
3637

3738
// FromData will find and optionally verify Confluent secrets in a given set of bytes.
3839
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
3940
dataStr := string(data)
4041

42+
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
4143
secretMatches := secretPat.FindAllStringSubmatch(dataStr, -1)
4244

43-
for _, match := range secretMatches {
44-
resSecret := strings.TrimSpace(match[1]) // Use index 1 for the captured group
45+
for _, match := range matches {
46+
resMatch := strings.TrimSpace(match[1])
4547

46-
s1 := detectors.Result{
47-
DetectorType: detectorspb.DetectorType_Confluent,
48-
Raw: []byte(resSecret),
49-
ExtraData: map[string]string{
50-
"rotation_guide": "https://docs.confluent.io/cloud/current/security/authenticate/workload-identities/service-accounts/api-keys/best-practices-api-keys.html#rotate-api-keys-regularly",
51-
"version": fmt.Sprintf("%d", s.Version()),
52-
},
53-
}
48+
for _, match := range secretMatches {
49+
resSecret := strings.TrimSpace(match[1]) // Use index 1 for the captured group
5450

55-
if verify {
56-
s1.Verified = verifyConfluentSecret(resSecret)
57-
}
51+
s1 := detectors.Result{
52+
DetectorType: detectorspb.DetectorType_Confluent,
53+
Raw: []byte(resMatch),
54+
RawV2: []byte(resMatch + resSecret),
55+
ExtraData: map[string]string{
56+
"rotation_guide": "https://docs.confluent.io/cloud/current/security/authenticate/workload-identities/service-accounts/api-keys/best-practices-api-keys.html#rotate-api-keys-regularly",
57+
"version": fmt.Sprintf("%d", s.Version()),
58+
},
59+
}
5860

59-
results = append(results, s1)
61+
if verify {
62+
s1.Verified = verifyConfluentSecret(resSecret)
63+
}
64+
65+
results = append(results, s1)
66+
}
6067
}
6168

6269
return results, nil

pkg/detectors/confluent/v2/confluent_integration_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ func TestConfluent_FromChunk(t *testing.T) {
1818
// Valid secret with proper CRC32 checksum
1919
validSecret := "cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipHZtDjw"
2020
// Invalid secret with wrong checksum
21-
invalidSecret := "cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipHZtDji"
21+
invalidSecret := "cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipHZtDje"
22+
key := "JSAOOCIC74SGECCP"
2223

2324
type args struct {
2425
ctx context.Context
@@ -37,7 +38,7 @@ func TestConfluent_FromChunk(t *testing.T) {
3738
s: Scanner{},
3839
args: args{
3940
ctx: context.Background(),
40-
data: []byte(fmt.Sprintf("You can find a confluent secret %s", validSecret)),
41+
data: []byte(fmt.Sprintf("You can find a confluent secret %s with key %s", validSecret, key)),
4142
verify: true,
4243
},
4344
want: []detectors.Result{
@@ -57,7 +58,7 @@ func TestConfluent_FromChunk(t *testing.T) {
5758
s: Scanner{},
5859
args: args{
5960
ctx: context.Background(),
60-
data: []byte(fmt.Sprintf("You can find a confluent secret %s but not valid", invalidSecret)), // the secret would satisfy the regex but not pass validation
61+
data: []byte(fmt.Sprintf("You can find a confluent secret %s with %s key but not valid", invalidSecret, key)), // the secret would satisfy the regex but not pass validation
6162
verify: true,
6263
},
6364
want: []detectors.Result{

pkg/detectors/confluent/v2/confluent_test.go

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,19 @@ import (
1212

1313
var (
1414
validPattern = `
15-
# Configuration File: config.yaml
16-
database:
17-
host: $DB_HOST
18-
port: $DB_PORT
19-
username: $DB_USERNAME
20-
password: $DB_PASS # IMPORTANT: Do not share this password publicly
15+
=== Confluent Cloud API key ===
2116
22-
api:
23-
auth_type: "Basic"
24-
in: "Header"
25-
confluent_secret: "cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipj0ObHQ"
26-
base_url: "https://api.example.com/v1/user"
17+
API key:
18+
JSAOOCIC74SGECCP
19+
20+
API secret:
21+
cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipHZtDjw
22+
23+
Resource scope:
24+
Cloud resource management
2725
28-
# Notes:
29-
# - Remember to rotate the secret every 90 days.
30-
# - The above credentials should only be used in a secure environment.
3126
`
32-
secret = "cfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipj0ObHQ"
27+
secret = "JSAOOCIC74SGECCPcfltT8d8RzkNseTMEDKcjNM1BZTFPHqRn/dQm9q7w6SjzZ12wZfwjaJdipHZtDjw"
3328
)
3429

3530
func TestConfluent_Pattern(t *testing.T) {

0 commit comments

Comments
 (0)