[INT-942] Add HumioAPIToken detector (#5258)

* [INT-942] Add HumioAPIToken detector

Add a TruffleHog detector for Humio/CrowdStrike Falcon LogScale API
tokens. These are personal and repository-scoped tokens in a
tilde-delimited base62 format ({24 or 32}~{44}) that grant read/write
access to LogScale repositories via the REST and GraphQL APIs.

Verification uses the read-only GET /api/v1/health-json endpoint.
Known SaaS regions (US and EU) are tried automatically; self-hosted or
CrowdStrike regional instances are supported via explicit endpoint
configuration. ExtraData surfaces token type (Personal API Token vs
Repository API Token) based on prefix length.

Feature-flag gated behind HumioAPITokenDetectorEnabled.

Co-authored-by: Cursor <[email protected]>

* Use realistic test inputs for pattern matching

Replace synthetic one-liner inputs with multi-line snippets that
mirror real-world contexts: Python client config, .env file, Docker
Compose environment block. Adopt require.NoError from testify to
match the convention in solarwindsobservability_test.go.

Co-authored-by: Cursor <[email protected]>

* Use url.JoinPath for verification endpoint URLs

Replace string concatenation with url.JoinPath to safely construct
verification URLs from base endpoints.

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Dave Hubbard
2026-09-08 09:22:21 -04:00
committed by GitHub
co-authored by Cursor
parent 166bf18f3a
commit 080c22fb8e
9 changed files with 657 additions and 7 deletions
+1
View File
@@ -576,6 +576,7 @@ func run(state overseer.State, logSync func() error) {
feature.MSTeamsWebhookV2DetectorEnabled.Store(true)
feature.SolarwindsDetectorEnabled.Store(true)
feature.WeightsAndBiasesV2DetectorEnabled.Store(true)
feature.HumioAPITokenDetectorEnabled.Store(true)
conf := &config.Config{}
if *configFilename != "" {
@@ -0,0 +1,168 @@
package humioapitoken
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"strings"
regexp "github.com/wasilibs/go-re2"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
)
type Scanner struct {
client *http.Client
detectors.EndpointSetter
}
var _ detectors.Detector = (*Scanner)(nil)
var _ detectors.EndpointCustomizer = (*Scanner)(nil)
var _ detectors.CloudProvider = (*Scanner)(nil)
func (Scanner) CloudEndpoint() string { return "https://cloud.us.humio.com" }
// additionalCloudEndpoints lists Humio/LogScale SaaS regions beyond the
// primary one returned by CloudEndpoint(). The CloudProvider interface
// only supports a single endpoint, so these are passed as found
// endpoints during verification to ensure tokens from any region are
// verified even when the scanned data contains no URL.
var additionalCloudEndpoints = []string{
"https://cloud.humio.com",
}
var (
defaultClient = common.SaneHttpClient()
// API tokens are base62 strings with a tilde (~) separator: a 24- or
// 32-character prefix and a fixed 44-character suffix. The tilde +
// exact segment lengths make this format distinctive enough that no
// PrefixRegex or surrounding-context anchor is needed.
// Example: pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR
keyPat = regexp.MustCompile(`\b([A-Za-z0-9]{24}(?:[A-Za-z0-9]{8})?~[A-Za-z0-9]{44})\b`)
)
func (s Scanner) Type() detector_typepb.DetectorType {
return detector_typepb.DetectorType_HumioAPIToken
}
func (s Scanner) Keywords() []string {
// The tilde separator in the token format is distinctive but too common
// in source code (URLs, paths, shell, bitwise ops) to use as a keyword.
// Te regex handles precision within matched chunks.
return []string{"humio", "logscale"}
}
func (s Scanner) Description() string {
return "Humio/CrowdStrike Falcon LogScale is a log management platform. API tokens grant read/write access to a specific LogScale repository via the REST and GraphQL APIs."
}
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
dataStr := string(data)
tokenMatches := make(map[string]struct{})
for _, match := range keyPat.FindAllStringSubmatch(dataStr, -1) {
t := strings.TrimSpace(match[1])
tokenMatches[t] = struct{}{}
}
for token := range tokenMatches {
r := detectors.Result{
DetectorType: detector_typepb.DetectorType_HumioAPIToken,
Raw: []byte(token),
SecretParts: map[string]string{"key": token},
ExtraData: map[string]string{"token_type": humioTokenType(token)},
}
if verify {
client := s.client
if client == nil {
client = defaultClient
}
// Verification only targets known SaaS regions (US via
// CloudEndpoint, EU via additionalCloudEndpoints) plus any
// endpoints explicitly configured by the operator (e.g.
// self-hosted instances). URLs discovered in scanned data are
// not used — arbitrary hosts can return 403 for non-auth
// reasons (WAF, CDN), causing false verification.
//
// Only non-nil errors overwrite lastErr so that a clean 401
// from the wrong region doesn't erase a transient failure
// (500, timeout) from a region that might be authoritative.
var lastErr error
for _, baseURL := range s.Endpoints(additionalCloudEndpoints...) {
isVerified, vErr := verifyAPIToken(ctx, client, baseURL, token)
r.Verified = isVerified
if vErr != nil {
lastErr = vErr
}
if isVerified {
lastErr = nil
r.ExtraData["endpoint"] = baseURL
break
}
}
r.SetVerificationError(lastErr, token)
}
results = append(results, r)
}
return results, nil
}
// humioTokenType classifies the token based on prefix length: 24-char
// prefixes are personal API tokens (PATs), 32-char prefixes are
// repository/view API tokens.
func humioTokenType(token string) string {
idx := strings.Index(token, "~")
if idx == 24 {
return "Personal API Token"
}
return "Repository API Token"
}
// verifyAPIToken hits the health-json endpoint, which is read-only and
// produces no side effects. The endpoint requires authentication and
// returns cluster health status on success.
//
// Response semantics: 200 means fully valid. 403 signals a recognized token
// blocked by an IP filter, so it still counts as verified. 401 means the
// token is unknown or expired.
func verifyAPIToken(ctx context.Context, client *http.Client, baseURL, token string) (bool, error) {
endpoint, err := url.JoinPath(baseURL, "/api/v1/health-json")
if err != nil {
return false, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return false, err
}
req.Header.Set("Authorization", "Bearer "+token)
res, err := client.Do(req)
if err != nil {
return false, err
}
defer func() {
_, _ = io.Copy(io.Discard, res.Body)
_ = res.Body.Close()
}()
switch res.StatusCode {
case http.StatusOK:
return true, nil
case http.StatusForbidden:
// Token was recognized but blocked (IP filter, permission change).
return true, nil
case http.StatusUnauthorized:
return false, nil
default:
return false, fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
}
}
@@ -0,0 +1,178 @@
//go:build detectors
// +build detectors
package humioapitoken
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
)
// newTestScanner returns a Scanner with the cloud endpoint configured, mirroring
// what DefaultDetectors() does at startup. Without this, Endpoints() returns
// nothing and the verification loop never runs.
func newTestScanner(client *http.Client) Scanner {
s := Scanner{client: client}
s.SetCloudEndpoint("https://cloud.us.humio.com")
s.UseCloudEndpoint(true)
return s
}
func TestHumioAPIToken_FromChunk(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors7")
if err != nil {
t.Fatalf("could not get test secrets from GCP: %s", err)
}
secret := testSecrets.MustGetField("HUMIOAPITOKEN")
inactiveSecret := testSecrets.MustGetField("HUMIOAPITOKEN_INACTIVE")
type args struct {
ctx context.Context
data []byte
verify bool
}
tests := []struct {
name string
s Scanner
args args
want []detectors.Result
wantErr bool
}{
{
name: "found, verified",
s: newTestScanner(nil),
args: args{
ctx: context.Background(),
data: []byte(fmt.Sprintf("You can find a humio api token %s within", secret)),
verify: true,
},
want: []detectors.Result{
{
DetectorType: detector_typepb.DetectorType_HumioAPIToken,
Verified: true,
},
},
wantErr: false,
},
{
name: "found, real secrets, verification error due to timeout",
s: newTestScanner(common.SaneHttpClientTimeOut(1 * time.Microsecond)),
args: args{
ctx: context.Background(),
data: []byte(fmt.Sprintf("You can find a humio api token %s within", secret)),
verify: true,
},
want: func() []detectors.Result {
r := detectors.Result{
DetectorType: detector_typepb.DetectorType_HumioAPIToken,
Verified: false,
}
r.SetVerificationError(context.DeadlineExceeded)
return []detectors.Result{r}
}(),
wantErr: false,
},
{
name: "found, real secrets, verification error due to unexpected api surface",
s: newTestScanner(common.ConstantResponseHttpClient(500, "{}")),
args: args{
ctx: context.Background(),
data: []byte(fmt.Sprintf("You can find a humio api token %s within", secret)),
verify: true,
},
want: func() []detectors.Result {
r := detectors.Result{
DetectorType: detector_typepb.DetectorType_HumioAPIToken,
Verified: false,
}
r.SetVerificationError(fmt.Errorf("unexpected HTTP response status 500"))
return []detectors.Result{r}
}(),
wantErr: false,
},
{
name: "found, unverified",
s: newTestScanner(nil),
args: args{
ctx: context.Background(),
data: []byte(fmt.Sprintf("You can find a humio api token %s within but not valid", inactiveSecret)),
verify: true,
},
want: []detectors.Result{
{
DetectorType: detector_typepb.DetectorType_HumioAPIToken,
Verified: false,
},
},
wantErr: false,
},
{
name: "not found",
s: newTestScanner(nil),
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) {
got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
if (err != nil) != tt.wantErr {
t.Errorf("HumioAPIToken.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])
}
gotErr := ""
if got[i].VerificationError() != nil {
gotErr = got[i].VerificationError().Error()
}
wantErr := ""
if tt.want[i].VerificationError() != nil {
wantErr = tt.want[i].VerificationError().Error()
}
if gotErr != wantErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.want[i].VerificationError(), got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "RawV2", "verificationError", "SecretParts", "ExtraData")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("HumioAPIToken.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) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
_, err := s.FromData(ctx, false, data)
if err != nil {
b.Fatal(err)
}
}
})
}
}
@@ -0,0 +1,292 @@
package humioapitoken
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/engine/ahocorasick"
)
var (
// 32-char prefix + tilde + 44-char suffix (repository API token)
validPattern32 = "pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR"
// 24-char prefix + tilde + 44-char suffix (personal API token)
validPattern24 = "abcDefGhiJklMnoPqrStUvWx~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR"
)
func TestHumioAPIToken_Pattern(t *testing.T) {
d := Scanner{}
ahoCorasickCore := ahocorasick.NewAhoCorasickCore([]detectors.Detector{d})
tests := []struct {
name string
input string
want []string
}{
{
name: "valid pattern - python client config",
input: `
from humiolib.HumioClient import HumioClient
client = HumioClient(
base_url="https://cloud.us.humio.com",
api_token="pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR",
)
results = client.search_repo("sandbox", "loglevel=ERROR")`,
want: []string{validPattern32},
},
{
name: "valid pattern - env file with PAT",
input: `
# LogScale personal access token for CI/CD pipeline
LOGSCALE_API_TOKEN=abcDefGhiJklMnoPqrStUvWx~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR
LOGSCALE_BASE_URL=https://cloud.humio.com
LOG_LEVEL=info`,
want: []string{validPattern24},
},
{
name: "valid pattern - logscale keyword in docker compose",
input: `
services:
log-shipper:
image: fluent/fluent-bit:latest
environment:
- LOGSCALE_TOKEN=pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR
- LOGSCALE_HOST=https://cloud.us.humio.com
restart: always`,
want: []string{validPattern32},
},
{
name: "valid pattern - ignore duplicate",
input: fmt.Sprintf("humio token = '%s' | '%s'", validPattern32, validPattern32),
want: []string{validPattern32},
},
{
name: "valid pattern - token far from keyword",
input: `
# Humio repository configuration
# Generated by setup wizard on 2025-01-15
api_token = "pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR"`,
want: []string{validPattern32},
},
{
name: "invalid pattern - tilde present but suffix too short",
input: `
from humiolib.HumioClient import HumioClient
client = HumioClient(api_token="pHUw1oLASALFmt2ppNvwCR0Meo2nHQ15~ECViF0Ce95uIqFGSS")`,
want: []string{},
},
{
name: "invalid pattern - tilde present but segments too short",
input: `
# humio config
token = "abc~def"`,
want: []string{},
},
{
name: "invalid pattern - wrong prefix length (28 chars)",
input: `
# humio config
token = "abcDefGhiJklMnoPqrStUvWxYzAb~ECViF0Ce95uIqFGSSatjKWX71EOzvkpVGSuc3zGYqJgR"`,
want: []string{},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
matchedDetectors := ahoCorasickCore.FindDetectorMatches([]byte(test.input))
if len(matchedDetectors) == 0 {
t.Errorf("keywords '%v' not matched by: %s", d.Keywords(), test.input)
return
}
results, err := d.FromData(context.Background(), false, []byte(test.input))
require.NoError(t, err)
if len(results) != len(test.want) {
t.Errorf("expected %d results, got %d", len(test.want), len(results))
return
}
actual := make(map[string]struct{}, len(results))
for _, r := range results {
if len(r.RawV2) > 0 {
actual[string(r.RawV2)] = struct{}{}
} else {
actual[string(r.Raw)] = struct{}{}
}
}
expected := make(map[string]struct{}, len(test.want))
for _, v := range test.want {
expected[v] = struct{}{}
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Errorf("%s diff: (-want +got)\n%s", test.name, diff)
}
})
}
}
// Exercise the verification logic against a mock health-json server. Each
// HTTP status code maps to a specific verified/error outcome — 403 counts as
// verified because the server recognized the token (just blocked by IP filter).
func TestHumioAPIToken_Verification(t *testing.T) {
tests := []struct {
name string
statusCode int
wantVerified bool
wantErr bool
}{
{"200 - valid token", http.StatusOK, true, false},
{"401 - unknown token", http.StatusUnauthorized, false, false},
{"403 - recognized but blocked", http.StatusForbidden, true, false},
{"500 - server error", http.StatusInternalServerError, false, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(tt.statusCode)
}))
defer ts.Close()
s := Scanner{}
s.SetCloudEndpoint(ts.URL)
s.UseCloudEndpoint(true)
input := fmt.Sprintf("humio_token = '%s'", validPattern32)
results, err := s.FromData(context.Background(), true, []byte(input))
if err != nil {
t.Fatalf("FromData error: %v", err)
}
if len(results) != 1 {
t.Fatalf("expected 1 result, got %d", len(results))
}
r := results[0]
if r.Verified != tt.wantVerified {
t.Errorf("Verified = %v, want %v", r.Verified, tt.wantVerified)
}
if tt.wantErr && r.VerificationError() == nil {
t.Error("expected verification error, got nil")
}
if !tt.wantErr && r.VerificationError() != nil {
t.Errorf("unexpected verification error: %v", r.VerificationError())
}
})
}
}
// Verify that a successful verification on a later endpoint clears any
// error from an earlier failed attempt (e.g. first endpoint returns 500,
// second returns 200).
func TestHumioAPIToken_Verification_StaleErrorCleared(t *testing.T) {
callCount := 0
ts500 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
callCount++
w.WriteHeader(http.StatusInternalServerError)
}))
defer ts500.Close()
ts200 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
callCount++
w.WriteHeader(http.StatusOK)
}))
defer ts200.Close()
s := Scanner{}
_ = s.SetConfiguredEndpoints(ts500.URL, ts200.URL)
input := fmt.Sprintf("humio_token = '%s'", validPattern32)
results, err := s.FromData(context.Background(), true, []byte(input))
if err != nil {
t.Fatalf("FromData error: %v", err)
}
if len(results) != 1 {
t.Fatalf("expected 1 result, got %d", len(results))
}
r := results[0]
if !r.Verified {
t.Error("expected Verified = true after second endpoint succeeded")
}
if r.VerificationError() != nil {
t.Errorf("stale verification error not cleared: %v", r.VerificationError())
}
}
// Verify that a clean 401 from the wrong region does not erase a transient
// error from an earlier endpoint. The verification error should survive so
// consumers know the result is uncertain, not definitively "not valid."
func TestHumioAPIToken_Verification_ErrorPreservedAcross401(t *testing.T) {
ts500 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer ts500.Close()
ts401 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
}))
defer ts401.Close()
s := Scanner{}
_ = s.SetConfiguredEndpoints(ts500.URL, ts401.URL)
input := fmt.Sprintf("humio_token = '%s'", validPattern32)
results, err := s.FromData(context.Background(), true, []byte(input))
if err != nil {
t.Fatalf("FromData error: %v", err)
}
if len(results) != 1 {
t.Fatalf("expected 1 result, got %d", len(results))
}
r := results[0]
if r.Verified {
t.Error("expected Verified = false")
}
if r.VerificationError() == nil {
t.Error("expected verification error to be preserved after 401 from another endpoint, got nil")
}
}
func TestHumioAPIToken_TokenType(t *testing.T) {
tests := []struct {
name string
token string
want string
}{
{"24-char prefix is Personal API Token", validPattern24, "Personal API Token"},
{"32-char prefix is Repository API Token", validPattern32, "Repository API Token"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := humioTokenType(tt.token)
if got != tt.want {
t.Errorf("humioTokenType() = %q, want %q", got, tt.want)
}
})
}
}
// Data without humio/logscale context must not reach this detector — the
// Aho-Corasick pre-filter should reject the chunk.
func TestHumioAPIToken_NoKeywordMatch(t *testing.T) {
d := Scanner{}
ahoCorasickCore := ahocorasick.NewAhoCorasickCore([]detectors.Detector{d})
input := fmt.Sprintf("some_generic_token = '%s'", validPattern32)
matchedDetectors := ahoCorasickCore.FindDetectorMatches([]byte(input))
if len(matchedDetectors) != 0 {
t.Errorf("expected no keyword match for input without humio/logscale context, got %d", len(matchedDetectors))
}
}
+4
View File
@@ -387,6 +387,7 @@ import (
hubspot_apikey_v2 "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/hubspot_apikey/v2"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/huggingface"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/humanity"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/humioapitoken"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/hunter"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/hybiscus"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/hypertrack"
@@ -1299,6 +1300,7 @@ func buildDetectorList() []detectors.Detector {
&hubspot_apikey_v2.Scanner{},
&huggingface.Scanner{},
&humanity.Scanner{},
&humioapitoken.Scanner{},
&hunter.Scanner{},
&hybiscus.Scanner{},
&hypertrack.Scanner{},
@@ -1894,6 +1896,8 @@ func buildDetectorList() []detectors.Detector {
return !feature.MSTeamsWebhookV2DetectorEnabled.Load()
case *solarwindsobservability.Scanner:
return !feature.SolarwindsDetectorEnabled.Load()
case *humioapitoken.Scanner:
return !feature.HumioAPITokenDetectorEnabled.Load()
case *weightsandbiasesv2.Scanner:
return !feature.WeightsAndBiasesV2DetectorEnabled.Load()
default:
+1
View File
@@ -151,6 +151,7 @@ var excludedFromDefaultList = map[detector_typepb.DetectorType]struct{}{
detector_typepb.DetectorType_NewRelicInsightsQueryKey: {},
detector_typepb.DetectorType_NewRelicMobileAppToken: {},
detector_typepb.DetectorType_SolarWindsObservability: {},
detector_typepb.DetectorType_HumioAPIToken: {},
// Reserved / special types.
detector_typepb.DetectorType_CustomRegex: {}, // added dynamically via engine config, not via buildDetectorList()
+1
View File
@@ -51,6 +51,7 @@ var (
MSTeamsWebhookV2DetectorEnabled atomic.Bool
SolarwindsDetectorEnabled atomic.Bool
WeightsAndBiasesV2DetectorEnabled atomic.Bool
HumioAPITokenDetectorEnabled atomic.Bool
)
type AtomicString struct {
+11 -7
View File
@@ -1125,6 +1125,7 @@ const (
DetectorType_NewRelicInsightsQueryKey DetectorType = 1067
DetectorType_NewRelicMobileAppToken DetectorType = 1068
DetectorType_SolarWindsObservability DetectorType = 1069
DetectorType_HumioAPIToken DetectorType = 1070
)
// Enum value maps for DetectorType.
@@ -2196,6 +2197,7 @@ var (
1067: "NewRelicInsightsQueryKey",
1068: "NewRelicMobileAppToken",
1069: "SolarWindsObservability",
1070: "HumioAPIToken",
}
DetectorType_value = map[string]int32{
"Alibaba": 0,
@@ -3264,6 +3266,7 @@ var (
"NewRelicInsightsQueryKey": 1067,
"NewRelicMobileAppToken": 1068,
"SolarWindsObservability": 1069,
"HumioAPIToken": 1070,
}
)
@@ -3299,7 +3302,7 @@ var File_detector_type_proto protoreflect.FileDescriptor
var file_detector_type_proto_rawDesc = []byte{
0x0a, 0x13, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x2a, 0xf3, 0x8b, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74,
0x74, 0x79, 0x70, 0x65, 0x2a, 0x87, 0x8c, 0x01, 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,
@@ -4418,12 +4421,13 @@ var file_detector_type_proto_rawDesc = []byte{
0x12, 0x1b, 0x0a, 0x16, 0x4e, 0x65, 0x77, 0x52, 0x65, 0x6c, 0x69, 0x63, 0x4d, 0x6f, 0x62, 0x69,
0x6c, 0x65, 0x41, 0x70, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xac, 0x08, 0x12, 0x1c, 0x0a,
0x17, 0x53, 0x6f, 0x6c, 0x61, 0x72, 0x57, 0x69, 0x6e, 0x64, 0x73, 0x4f, 0x62, 0x73, 0x65, 0x72,
0x76, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x10, 0xad, 0x08, 0x42, 0x41, 0x5a, 0x3f, 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, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x70, 0x62, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x76, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x10, 0xad, 0x08, 0x12, 0x12, 0x0a, 0x0d, 0x48,
0x75, 0x6d, 0x69, 0x6f, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xae, 0x08, 0x42,
0x41, 0x5a, 0x3f, 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, 0x5f, 0x74, 0x79, 0x70, 0x65,
0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
+1
View File
@@ -1071,4 +1071,5 @@ enum DetectorType {
NewRelicInsightsQueryKey = 1067;
NewRelicMobileAppToken = 1068;
SolarWindsObservability = 1069;
HumioAPIToken = 1070;
}