diff --git a/CHANGELOG.md b/CHANGELOG.md index fa7d7ed2f37d2..6ce2e0d603521 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - `attributesprocessor`: Support filter by severity (#9132) - `processor/transform`: Add transformation of logs (#9368) - `datadogexporter`: Add `metrics::summaries::mode` to specify export mode for summaries (#8846) +- `datadogexporter`: Add `api.fail_on_invalid_key` to fail fast if api key is invalid (#9426) ### 🧰 Bug fixes 🧰 diff --git a/exporter/datadogexporter/config/config.go b/exporter/datadogexporter/config/config.go index 05311097154a8..b19e67cc3a31f 100644 --- a/exporter/datadogexporter/config/config.go +++ b/exporter/datadogexporter/config/config.go @@ -21,12 +21,11 @@ import ( "regexp" "strings" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/internal/metadata/valid" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.uber.org/zap" - - "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/internal/metadata/valid" ) var ( @@ -58,6 +57,10 @@ type APIConfig struct { // It can also be set through the `DD_SITE` environment variable (Deprecated: [v0.47.0] set environment variable explicitly on configuration instead). // The default value is "datadoghq.com". Site string `mapstructure:"site"` + + // FailOnInvalidKey states whether to exit on invalid api key. + // The default value is false. + FailOnInvalidKey bool `mapstructure:"fail_on_invalid_key"` } // MetricsConfig defines the metrics exporter specific configuration options diff --git a/exporter/datadogexporter/example/config.yaml b/exporter/datadogexporter/example/config.yaml index c3a830e8c5a86..42a579db5c38a 100644 --- a/exporter/datadogexporter/example/config.yaml +++ b/exporter/datadogexporter/example/config.yaml @@ -83,6 +83,11 @@ exporters: # # site: datadoghq.com + ## @param fail_on_invalid_key - boolean - optional - default: false + ## Whether to exit on invalid api key. + # + # fail_on_invalid_key: false + ## @param tls - custom object - optional # TLS settings for HTTPS communications. # tls: diff --git a/exporter/datadogexporter/internal/utils/api.go b/exporter/datadogexporter/internal/utils/api.go index 02a8296650ba5..b40f4d3ab3f79 100644 --- a/exporter/datadogexporter/internal/utils/api.go +++ b/exporter/datadogexporter/internal/utils/api.go @@ -28,16 +28,22 @@ func CreateClient(APIKey string, endpoint string) *datadog.Client { } // ValidateAPIKey checks that the provided client was given a correct API key. -func ValidateAPIKey(logger *zap.Logger, client *datadog.Client) { +// If `api.fail_on_invalid_key` is enabled, +func ValidateAPIKey(logger *zap.Logger, client *datadog.Client, failOnInvalidKey bool) { logger.Info("Validating API key.") - res, err := client.Validate() - if err != nil { - logger.Warn("Error while validating API key.", zap.Error(err)) - } - - if res { + valid, err := client.Validate() + if err == nil && valid { logger.Info("API key validation successful.") - } else { - logger.Warn("API key validation failed.") + return + } + switch { + case err != nil && failOnInvalidKey: + logger.Fatal("Error while validating API key.", zap.Error(err)) + case err != nil && !failOnInvalidKey: + logger.Warn("Error while validating API key.", zap.Error(err)) + case !valid && failOnInvalidKey: + logger.Fatal("API Key validation failed.") + case !valid && !failOnInvalidKey: + logger.Warn("API Key validation failed.") } } diff --git a/exporter/datadogexporter/metrics_exporter.go b/exporter/datadogexporter/metrics_exporter.go index 3dc1976f913de..65981f9a2671d 100644 --- a/exporter/datadogexporter/metrics_exporter.go +++ b/exporter/datadogexporter/metrics_exporter.go @@ -105,7 +105,7 @@ func newMetricsExporter(ctx context.Context, params component.ExporterCreateSett client.ExtraHeader["User-Agent"] = utils.UserAgent(params.BuildInfo) client.HttpClient = utils.NewHTTPClient(cfg.TimeoutSettings, cfg.LimitedHTTPClientSettings.TLSSetting.InsecureSkipVerify) - utils.ValidateAPIKey(params.Logger, client) + utils.ValidateAPIKey(params.Logger, client, cfg.API.FailOnInvalidKey) tr, err := translatorFromConfig(params.Logger, cfg) if err != nil { diff --git a/exporter/datadogexporter/traces_exporter.go b/exporter/datadogexporter/traces_exporter.go index 55c8f6df80e6c..7c907af93972c 100644 --- a/exporter/datadogexporter/traces_exporter.go +++ b/exporter/datadogexporter/traces_exporter.go @@ -68,7 +68,7 @@ var ( func newTracesExporter(ctx context.Context, params component.ExporterCreateSettings, cfg *config.Config, onceMetadata *sync.Once) *traceExporter { // client to send running metric to the backend & perform API key validation client := utils.CreateClient(cfg.API.Key, cfg.Metrics.TCPAddr.Endpoint) - utils.ValidateAPIKey(params.Logger, client) + utils.ValidateAPIKey(params.Logger, client, cfg.API.FailOnInvalidKey) // removes potentially sensitive info and PII, approach taken from serverless approach // https://github.com/DataDog/datadog-serverless-functions/blob/11f170eac105d66be30f18eda09eca791bc0d31b/aws/logs_monitoring/trace_forwarder/cmd/trace/main.go#L43