diff --git a/extension/ingestionapikeyauthextension/config.go b/extension/ingestionapikeyauthextension/config.go new file mode 100644 index 0000000..cec3c6e --- /dev/null +++ b/extension/ingestionapikeyauthextension/config.go @@ -0,0 +1,44 @@ +package ingestionapikeyauthextension + +import ( + "fmt" + "time" +) + +type EndpointSettings struct { + Url string `mapstructure:"url"` +} + +type CacheSettings struct { + ValidSize int `mapstructure:"valid_size"` + ValidTtl time.Duration `mapstructure:"valid_ttl"` + InvalidSize int `mapstructure:"invalid_size"` +} + +type Config struct { + Endpoint *EndpointSettings `mapstructure:"endpoint,omitempty"` + Cache *CacheSettings `mapstructure:"cache,omitempty"` +} + +func (cfg *Config) Validate() error { + if cfg.Endpoint == nil { + return fmt.Errorf("required endpoint paramater") + } + if len(cfg.Endpoint.Url) == 0 { + return fmt.Errorf("required endpoint.url paramater") + } + + if cfg.Cache == nil { + return fmt.Errorf("required cache paramater") + } + if cfg.Cache.ValidSize <= 0 { + return fmt.Errorf("paramater cache.valid_size must be a postive value") + } + if cfg.Cache.ValidTtl <= 0 { + return fmt.Errorf("paramater cache.valid_ttl_seconds must be a postive value") + } + if cfg.Cache.InvalidSize <= 0 { + return fmt.Errorf("paramater cache.invalid_size must be a postive value") + } + return nil +} diff --git a/extension/ingestionapikeyauthextension/config_test.go b/extension/ingestionapikeyauthextension/config_test.go new file mode 100644 index 0000000..b2355e5 --- /dev/null +++ b/extension/ingestionapikeyauthextension/config_test.go @@ -0,0 +1,88 @@ +package ingestionapikeyauthextension + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" + "path/filepath" + "testing" + "time" +) + +func TestLoadConfig(t *testing.T) { + tests := []struct { + id component.ID + expected component.Config + expectedErr bool + }{ + { + id: component.NewID(Type), + expectedErr: true, + }, + { + id: component.NewIDWithName(Type, "empty_endpoint"), + expectedErr: true, + }, + { + id: component.NewIDWithName(Type, "empty_url"), + expectedErr: true, + }, + { + id: component.NewIDWithName(Type, "missing_cache"), + expected: &Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:8091/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 100, + ValidTtl: 5 * time.Minute, + InvalidSize: 100, + }, + }, + }, + { + id: component.NewIDWithName(Type, "empty_cache"), + expected: &Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:8091/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 100, + ValidTtl: 5 * time.Minute, + InvalidSize: 100, + }, + }, + }, + { + id: component.NewIDWithName(Type, "valid"), + expected: &Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:8091/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 10, + ValidTtl: 20 * time.Second, + InvalidSize: 30, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.id.String(), func(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub(tt.id.String()) + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + if tt.expectedErr { + assert.Error(t, component.ValidateConfig(cfg)) + return + } + assert.NoError(t, component.ValidateConfig(cfg)) + assert.Equal(t, tt.expected, cfg) + }) + } +} diff --git a/extension/ingestionapikeyauthextension/extension.go b/extension/ingestionapikeyauthextension/extension.go new file mode 100644 index 0000000..21d2806 --- /dev/null +++ b/extension/ingestionapikeyauthextension/extension.go @@ -0,0 +1,148 @@ +package ingestionapikeyauthextension + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "github.com/hashicorp/golang-lru/v2/expirable" + "go.opentelemetry.io/collector/client" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension/auth" + "log" + "net/http" + "time" +) + +var ( + errNoAuth = errors.New("missing Authorization header") + errInternal = errors.New("internal error") + errAuthServerUnavailable = errors.New("auth server unavailable") + errForbidden = errors.New("forbidden") +) + +type extensionContext struct { + config *Config + httpClient http.Client + //we have two caches one for invalid keys, it maps auth key to nothing now but in the future we can map it to tenant ID + //it is LRU cache with TTL to delete unused keys after some time, the key should be always expired even if is constantly + //used, otherwise a key ma be invalidated and not deleted from the cache (because is still used). + validKeysCache *expirable.LRU[string, string] + //the cache stores last invalid keys to reject only valid collectors but without updated API key (e.g. expired) + //the cache can't prevent DoS or brute force attacks, it should be prevented on LB or API Gateway + //the cache maps maps auth key to an error but only "non transient" errors like Forbidden and shouldn't be used for transient + //issues (like authorization service unavailable). + invalidKeysCache *expirable.LRU[string, error] +} + +func newServerAuthExtension(cfg *Config) (auth.Server, error) { + exCtx := extensionContext{ + config: cfg, + validKeysCache: expirable.NewLRU[string, string](cfg.Cache.ValidSize, nil, cfg.Cache.ValidTtl), + invalidKeysCache: expirable.NewLRU[string, error](cfg.Cache.InvalidSize, nil, 0), + } + return auth.NewServer( + auth.WithServerStart(exCtx.serverStart), + auth.WithServerAuthenticate(exCtx.authenticate), + ), nil +} + +func (exCtx *extensionContext) serverStart(context.Context, component.Host) error { + httpClient := http.Client{ + Timeout: 5 * time.Second, // TODO configure timeout + } + + exCtx.httpClient = httpClient + + return nil +} + +func (exCtx *extensionContext) authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { + authorizationHeader := getAuthHeader(headers) + if authorizationHeader == "" { + return ctx, errNoAuth + } + + err := checkAuthorizationHeaderUseCache(authorizationHeader, exCtx) + if err != nil { + return ctx, err + } + + cl := client.FromContext(ctx) + return client.NewContext(ctx, cl), nil +} + +var authHeaders = [2]string{"authorization", "Authorization"} + +// Extract value of "Authorization" header, empty string - the header is missing. +func getAuthHeader(headers map[string][]string) string { + for _, authHeaderName := range authHeaders { + authHeader, ok := headers[authHeaderName] + + if ok && len(authHeader) > 0 { + return authHeader[0] + } + } + + return "" +} + +// Check if an Ingestion API Key is inside caches otherwise use a remote server to authorize it +func checkAuthorizationHeaderUseCache(authorizationHeader string, exCtx *extensionContext) error { + // check if the key is stored in "validKeysCache" cache, so we know the Key is valid. + _, ok := exCtx.validKeysCache.Get(authorizationHeader) + if ok { + return nil + } + + // check if the key is stored in "invalidKeysCache" cache, so we know the Key is invalid, reject it immediately + er, ok := exCtx.invalidKeysCache.Get(authorizationHeader) + if ok { + return er + } + + // otherwise use a remote server to authorize the key + return checkAuthorizationHeader(authorizationHeader, exCtx) +} + +type AuthorizeRequestBody struct { + ApiKey string `json:"apiKey"` +} + +// Authorizes an Ingestion API Key (value of Authorization header) with the remote authorization server. +// The function stores the result (valid keys but also non-transient errors) in the cache. +func checkAuthorizationHeader(authorizationHeader string, exCtx *extensionContext) error { + log.Println("Sending authorization request...") + request := AuthorizeRequestBody{ + ApiKey: authorizationHeader, + } + jsonData, err := json.Marshal(request) + if err != nil { + log.Print("Can't encode api request to JSON ", err) + return errInternal //it shouldn't happen, something is wrong with the implementation + } + + req, err := http.NewRequest(http.MethodPost, exCtx.config.Endpoint.Url, bytes.NewReader(jsonData)) + if err != nil { + log.Print("Can't create authorization request ", err) + return errInternal + } + + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Print("Authorization endpoint returned an error ", err) + return errAuthServerUnavailable + } + + if res.StatusCode == 403 { + exCtx.invalidKeysCache.Add(authorizationHeader, errForbidden) + return errForbidden + } + + if res.StatusCode == 204 { + exCtx.validKeysCache.Add(authorizationHeader, "") //In future we can store tenant ID in the cache + return nil + } + + return errInternal +} diff --git a/extension/ingestionapikeyauthextension/extension_test.go b/extension/ingestionapikeyauthextension/extension_test.go new file mode 100644 index 0000000..75069f7 --- /dev/null +++ b/extension/ingestionapikeyauthextension/extension_test.go @@ -0,0 +1,182 @@ +package ingestionapikeyauthextension + +import ( + "context" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component/componenttest" + "net/http" + "net/http/httptest" + "testing" + "time" +) + +func TestExtension_NoHeader(t *testing.T) { + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:8091/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{}) + assert.Equal(t, errNoAuth, err) +} + +func TestExtension_AuthServerUnavailable(t *testing.T) { + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:1/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{"authorization": {"key"}}) + assert.Equal(t, errAuthServerUnavailable, err) +} + +func TestExtension_InvalidKey(t *testing.T) { + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(403) + })) + + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: testServer.URL, + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{"authorization": {"key"}}) + assert.Equal(t, errForbidden, err) +} + +func TestExtension_Authorized(t *testing.T) { + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(204) + })) + + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: testServer.URL, + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{"authorization": {"key"}}) + require.NoError(t, err) +} + +func TestExtension_AuthorizedWithCamelcaseHeader(t *testing.T) { + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(204) + })) + + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: testServer.URL, + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{"Authorization": {"key"}}) + require.NoError(t, err) +} + +func TestExtension_ValidKeysShouldBeCached(t *testing.T) { + var requestCounter = 0 + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + println(requestCounter) + if requestCounter == 0 { + res.WriteHeader(204) + } else if requestCounter == 1 { + res.WriteHeader(403) + } else { + t.Fatal("The second request should be cached so it shouldn't hit the server") + } + requestCounter += 1 + })) + + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: testServer.URL, + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 3, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + _, err = ext.Authenticate(context.Background(), map[string][]string{"Authorization": {"key"}}) + require.NoError(t, err) + //it should be loaded from the cache, it is the same cache as in the previous request + _, err = ext.Authenticate(context.Background(), map[string][]string{"Authorization": {"key"}}) + require.NoError(t, err) + //send one more request, but with a different key, it shouldn't hit the cache + _, err = ext.Authenticate(context.Background(), map[string][]string{"authorization": {"key_new"}}) + assert.Equal(t, errForbidden, err) +} + +func TestExtension_InvalidKeyShouldBeCached(t *testing.T) { + var requestCounter = 0 + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + println(requestCounter) + if requestCounter == 0 { + res.WriteHeader(503) + } else if requestCounter == 1 { + res.WriteHeader(403) + } else { + t.Fatal("The second request should be cached so it shouldn't hit the server") + } + requestCounter += 1 + })) + + ext, err := newServerAuthExtension(&Config{ + Endpoint: &EndpointSettings{ + Url: testServer.URL, + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30 * time.Second, + InvalidSize: 1, + }, + }) + require.NoError(t, err) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + //server is broken and returns 503, it shouldn't be cached + _, err = ext.Authenticate(context.Background(), map[string][]string{"Authorization": {"invalid_key"}}) + assert.Equal(t, errInternal, err) + //The server is fixed so teh response should be cached + _, err = ext.Authenticate(context.Background(), map[string][]string{"Authorization": {"invalid_key"}}) + assert.Equal(t, errForbidden, err) + //the previous request is cached so it shouldn't hit the server + _, err = ext.Authenticate(context.Background(), map[string][]string{"authorization": {"invalid_key"}}) + assert.Equal(t, errForbidden, err) +} diff --git a/extension/ingestionapikeyauthextension/factory.go b/extension/ingestionapikeyauthextension/factory.go new file mode 100644 index 0000000..3ad5ad9 --- /dev/null +++ b/extension/ingestionapikeyauthextension/factory.go @@ -0,0 +1,36 @@ +package ingestionapikeyauthextension + +import ( + "context" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension" +) + +var ( + Type = component.MustNewType("ingestion_api_key_auth") +) + +func NewFactory() extension.Factory { + return extension.NewFactory( + Type, + createDefaultConfig, + createExtension, + component.StabilityLevelAlpha, + ) +} + +func createDefaultConfig() component.Config { + return &Config{ + Cache: &CacheSettings{ + ValidSize: 100, + ValidTtl: 5 * time.Minute, + InvalidSize: 100, + }, + } +} + +func createExtension(_ context.Context, _ extension.CreateSettings, cfg component.Config) (extension.Extension, error) { + return newServerAuthExtension(cfg.(*Config)) +} diff --git a/extension/ingestionapikeyauthextension/factory_test.go b/extension/ingestionapikeyauthextension/factory_test.go new file mode 100644 index 0000000..ba73bb9 --- /dev/null +++ b/extension/ingestionapikeyauthextension/factory_test.go @@ -0,0 +1,47 @@ +package ingestionapikeyauthextension + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/extension/extensiontest" +) + +func TestCreateDefaultConfig(t *testing.T) { + expected := &Config{ + Cache: &CacheSettings{ + ValidSize: 100, + ValidTtl: 5 * time.Minute, + InvalidSize: 100, + }, + } + actual := createDefaultConfig() + assert.Equal(t, expected, createDefaultConfig()) + assert.NoError(t, componenttest.CheckConfigStruct(actual)) +} + +func TestCreateExtension_ValidConfig(t *testing.T) { + cfg := &Config{ + Endpoint: &EndpointSettings{ + Url: "http://localhost:8091/authorize", + }, + Cache: &CacheSettings{ + ValidSize: 2, + ValidTtl: 30, + InvalidSize: 3, + }, + } + + ext, err := createExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg) + assert.NoError(t, err) + assert.NotNil(t, ext) +} + +func TestNewFactory(t *testing.T) { + f := NewFactory() + assert.NotNil(t, f) + assert.Equal(t, f.Type(), Type) +} diff --git a/extension/ingestionapikeyauthextension/go.mod b/extension/ingestionapikeyauthextension/go.mod new file mode 100644 index 0000000..c6d2065 --- /dev/null +++ b/extension/ingestionapikeyauthextension/go.mod @@ -0,0 +1,52 @@ +module ingestionapikeyauthextension + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.1-0.20240315172937-3b5aee0c7a16 + go.opentelemetry.io/collector/confmap v0.96.1-0.20240315172937-3b5aee0c7a16 + go.opentelemetry.io/collector/extension v0.96.1-0.20240315172937-3b5aee0c7a16 + go.opentelemetry.io/collector/extension/auth v0.96.1-0.20240315172937-3b5aee0c7a16 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +go 1.22.1 diff --git a/extension/ingestionapikeyauthextension/go.sum b/extension/ingestionapikeyauthextension/go.sum new file mode 100644 index 0000000..189436a --- /dev/null +++ b/extension/ingestionapikeyauthextension/go.sum @@ -0,0 +1,141 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/collector v0.96.0 h1:qXA3biNps8LPYYCTJwepGu58sW0XInmwnQbkkWZchIg= +go.opentelemetry.io/collector v0.96.0/go.mod h1:/i3zyRg23r7vloTLzKG/mRI2VkEt1Q4ARXbe3vKnAaE= +go.opentelemetry.io/collector/component v0.96.1-0.20240315172937-3b5aee0c7a16 h1:Is9uHOav+UViEFSyTl/I7Vk2zymZTSw9c6iBVn4/fRI= +go.opentelemetry.io/collector/component v0.96.1-0.20240315172937-3b5aee0c7a16/go.mod h1:0evn//YPgN/5VmbbD4JS0yH3ikWxwROQN1MKEOM/U3M= +go.opentelemetry.io/collector/config/configtelemetry v0.96.0 h1:Q9bSLPUzJUFG+P8eQ7W25Feko8yjdB7dK98V7hmUxCA= +go.opentelemetry.io/collector/config/configtelemetry v0.96.0/go.mod h1:tl8sI2RE3LSgJ0HjpadYpIwsKzw/CRA0nZUXLzMAZS0= +go.opentelemetry.io/collector/confmap v0.96.1-0.20240315172937-3b5aee0c7a16 h1:as8mEhxxXrdtz4cNZyCJFtfORWeEVVDnFjhE9XNEwAA= +go.opentelemetry.io/collector/confmap v0.96.1-0.20240315172937-3b5aee0c7a16/go.mod h1:AnJmZcZoOLuykSXGiAf3shi11ZZk5ei4tZd9dDTTpWE= +go.opentelemetry.io/collector/consumer v0.96.0 h1:JN4JHelp5EGMGoC2UVelTMG6hyZjgtgdLLt5eZfVynU= +go.opentelemetry.io/collector/consumer v0.96.0/go.mod h1:Vn+qzzKgekDFayCVV8peSH5Btx1xrt/bmzD9gTxgidQ= +go.opentelemetry.io/collector/extension v0.96.1-0.20240315172937-3b5aee0c7a16 h1:ETaJM2DKhBVMAEDexHafD+7W/HpFze7SbtYJE/w2zpY= +go.opentelemetry.io/collector/extension v0.96.1-0.20240315172937-3b5aee0c7a16/go.mod h1:H0IqtDdwT5WcXlikiaEB7rJTg3s9o04wNmyqRuG45PQ= +go.opentelemetry.io/collector/extension/auth v0.96.1-0.20240315172937-3b5aee0c7a16 h1:4PXtYQGb6ExvaNrONV//eZIpzbJFf+TTEQ5gkO3Pnv4= +go.opentelemetry.io/collector/extension/auth v0.96.1-0.20240315172937-3b5aee0c7a16/go.mod h1:oSbRWTzHAJm/Lb0VoK8GJ9FBOve/CaCpHnmQZRSkTT4= +go.opentelemetry.io/collector/pdata v1.3.0 h1:JRYN7tVHYFwmtQhIYbxWeiKSa2L1nCohyAs8sYqKFZo= +go.opentelemetry.io/collector/pdata v1.3.0/go.mod h1:t7W0Undtes53HODPdSujPLTnfSR5fzT+WpL+RTaaayo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/extension/ingestionapikeyauthextension/testdata/config.yaml b/extension/ingestionapikeyauthextension/testdata/config.yaml new file mode 100644 index 0000000..6897c0a --- /dev/null +++ b/extension/ingestionapikeyauthextension/testdata/config.yaml @@ -0,0 +1,25 @@ +ingestion_api_key_auth: + +ingestion_api_key_auth/empty_endpoint: + endpoint: + +ingestion_api_key_auth/empty_url: + endpoint: + url: + +ingestion_api_key_auth/missing_cache: + endpoint: + url: http://localhost:8091/authorize + +ingestion_api_key_auth/empty_cache: + endpoint: + url: http://localhost:8091/authorize + cache: + +ingestion_api_key_auth/valid: + endpoint: + url: http://localhost:8091/authorize + cache: + valid_size: 10 + valid_ttl: 20s + invalid_size: 30 \ No newline at end of file diff --git a/go.work b/go.work index 02788c4..8ff465f 100644 --- a/go.work +++ b/go.work @@ -6,5 +6,6 @@ use ( ./exporter/stackstateexporter ./extension/stsapitokenextension ./extension/stsauthenticationextension + ./extension/ingestionapikeyauthextension ./processor/stackstateprocessor ) diff --git a/go.work.sum b/go.work.sum index 5dc8231..cf55d26 100644 --- a/go.work.sum +++ b/go.work.sum @@ -349,6 +349,7 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= @@ -373,9 +374,11 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 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= @@ -400,6 +403,7 @@ github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -505,6 +509,7 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpsp github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615 h1:/mD+ABZyXD39BzJI2XyRJlqdZG11gXFo0SSynL+OFeU= github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM= @@ -638,20 +643,25 @@ go.opentelemetry.io/contrib/config v0.1.1 h1:lIUTrMWkfDE0GvzBLhwv6ATDB1vntrnTsRv go.opentelemetry.io/contrib/config v0.1.1/go.mod h1:rDrK4+PS6Cs+WIphU/GO5Sk4TGV36lEQqk/Z1vZkaLI= go.opentelemetry.io/contrib/config v0.3.0 h1:nJxYSB7/8fckSya4EAFyFGxIytMvNlQInXSmhz/OKKg= go.opentelemetry.io/contrib/config v0.3.0/go.mod h1:tQW0mY8be9/LGikwZNYno97PleUhF/lMal9xJ1TC2vo= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0 h1:D/cXD+03/UOphyyT87NX6h+DlU+BnplN6/P6KJwsgGc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0/go.mod h1:L669qRGbPBwLcftXLFnTVFO6ES/GyMAvITLdvRjEAIM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.23.0 h1:VZrBiTXzP3FErizsdF1JQj0qf0yA8Ktt6LAcjUhZqbc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.23.0/go.mod h1:xkkwo777b9MEfsyD1yUZa4g+7MCqqWAP3r2tTSZePRc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.0 h1:cZXHUQvCx7YMdjGu0AlmoArUz7NZ7K6WWsT4cjSkzc0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.0/go.mod h1:OHlshrAeSV9uiVQs1n+c0FVCyo8L0NrYzVf5GuLllRo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= go.opentelemetry.io/otel/exporters/prometheus v0.45.1/go.mod h1:wnHAfKRav5Dfp4iZhyWZ7SzQfT+rDZpEpYG7To+qJ1k= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.23.0 h1:f4N/tfYchDXfM78Ng5KKO7OjrShVzww1g4oYxZ7tyMA= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.23.0/go.mod h1:v1gipIZLj3qtxR1L1F7jF/WaPFA5ptuHk52+eq9SSRg= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= @@ -672,6 +682,7 @@ golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72 golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA= @@ -760,6 +771,7 @@ golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -804,6 +816,7 @@ golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -931,6 +944,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go. google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405 h1:o4S3HvTUEXgRsNSUQsALDVog0O9F/U1JJlHmmUN8Uas= google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw=