Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[exporter/azuredataexplorerexporter] add azure default auth #35835

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .chloggen/add_azure_default_auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: azuredataexplorerexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add new configuration option `use_default_auth` to enable default authentication for Azure Data Explorer. This option allows users to leverage workload identity for authentication.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33667]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
13 changes: 10 additions & 3 deletions exporter/azuredataexplorerexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ This exporter sends metrics, logs and trace data to
The following settings are required:

- `cluster_uri` (no default): The cluster name of the provisioned ADX cluster to ingest the data.
- `application_id` (no default): The client id to connect to the cluster and ingest data.
- `application_key` (no default): The cluster secret corresponding to the client id.
- `tenant_id` (no default): The tenant id where the application_id is referenced from.

One authentication method is required:
- Service principal:
- `application_id` (no default): The client id to connect to the cluster and ingest data.
- `application_key` (no default): The cluster secret corresponding to the client id.
- `tenant_id` (no default): The tenant id where the application_id is referenced from.
- Managed identity:
- `managed_identity_id` (no default): The managed identity id to authenticate with. Set to "system" for system-assigned managed identity. Set the MI client Id (GUID) for user-assigned managed identity.
- Default authentication:
- `use_default_auth` (no default): Set to true to use the Azure [default authentication](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#2-authenticate-with-azure). This is an optional setting and is set to false by default.
dmitryax marked this conversation as resolved.
Show resolved Hide resolved

The following settings can be optionally configured and have default values:
> Note that the database tables are expected to be created upfront before the exporter is in operation , the definition of these are in the section [Database and Table definition scripts](#database-and-table-definition-scripts)
Expand Down
2 changes: 2 additions & 0 deletions exporter/azuredataexplorerexporter/adx_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ func createKcsb(config *Config, version string) *kusto.ConnectionStringBuilder {
isSystemManagedIdentity := strings.EqualFold(strings.TrimSpace(config.ManagedIdentityID), "SYSTEM")
// If the user has managed identity done, use it. For System managed identity use the MI as system
switch {
case config.UseDefaultAuth:
kcsb = kusto.NewConnectionStringBuilder(config.ClusterURI).WithDefaultAzureCredential()
case !isManagedIdentity:
kcsb = kusto.NewConnectionStringBuilder(config.ClusterURI).WithAadAppKey(config.ApplicationID, string(config.ApplicationKey), config.TenantID)
case isManagedIdentity && isSystemManagedIdentity:
Expand Down
12 changes: 12 additions & 0 deletions exporter/azuredataexplorerexporter/adx_exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func TestCreateKcsb(t *testing.T) {
name string // name of the test
config Config // config for the test
isMsi bool // is MSI enabled
isDefaultAuth bool // is default authentication enabled
applicationID string // application id
managedIdentityID string // managed identity id
}{
Expand Down Expand Up @@ -216,6 +217,15 @@ func TestCreateKcsb(t *testing.T) {
managedIdentityID: "636d798f-b005-41c9-9809-81a5e5a12b2e",
applicationID: "",
},
{
name: "workload identity",
config: Config{
ClusterURI: "https://CLUSTER.kusto.windows.net",
Database: "tests",
UseDefaultAuth: true,
},
isDefaultAuth: true,
},
}
for i := range tests {
tt := tests[i]
Expand All @@ -229,6 +239,8 @@ func TestCreateKcsb(t *testing.T) {
wantManagedID := tt.managedIdentityID
assert.Equal(t, wantManagedID, gotKcsb.ManagedServiceIdentity)
assert.Equal(t, "https://CLUSTER.kusto.windows.net", gotKcsb.DataSource)
wantIsDefault := tt.isDefaultAuth
assert.Equal(t, wantIsDefault, gotKcsb.DefaultAuth)
})
}
}
Expand Down
21 changes: 18 additions & 3 deletions exporter/azuredataexplorerexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Config struct {
ApplicationKey configopaque.String `mapstructure:"application_key"`
TenantID string `mapstructure:"tenant_id"`
ManagedIdentityID string `mapstructure:"managed_identity_id"`
UseDefaultAuth bool `mapstructure:"use_default_auth"`
Database string `mapstructure:"db_name"`
MetricTable string `mapstructure:"metrics_table_name"`
LogTable string `mapstructure:"logs_table_name"`
Expand All @@ -46,9 +47,23 @@ func (adxCfg *Config) Validate() error {
if isClusterURIEmpty {
return errors.New(`clusterURI config is mandatory`)
}
// Parameters for AD App Auth or Managed Identity Auth are mandatory
if isAppAuthEmpty && isManagedAuthEmpty {
return errors.New(`either ["application_id" , "application_key" , "tenant_id"] or ["managed_identity_id"] are needed for auth`)
// Parameters for AD App Auth or Managed Identity Auth or Default Auth are mandatory
authMethods := 0

if !isAppAuthEmpty {
authMethods++
}

if !isManagedAuthEmpty {
authMethods++
}

if adxCfg.UseDefaultAuth {
authMethods++
}

if authMethods != 1 {
return errors.New(`either ["application_id" , "application_key" , "tenant_id"] or ["managed_identity_id"] or ["use_default_auth"] must be provided for auth`)
}

if !(adxCfg.IngestionType == managedIngestType || adxCfg.IngestionType == queuedIngestTest || isEmpty(adxCfg.IngestionType)) {
Expand Down
14 changes: 13 additions & 1 deletion exporter/azuredataexplorerexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestLoadConfig(t *testing.T) {
},
{
id: component.NewIDWithName(metadata.Type, "2"),
errorMessage: `either ["application_id" , "application_key" , "tenant_id"] or ["managed_identity_id"] are needed for auth`,
errorMessage: `either ["application_id" , "application_key" , "tenant_id"] or ["managed_identity_id"] or ["use_default_auth"] must be provided for auth`,
},
{
id: component.NewIDWithName(metadata.Type, "3"),
Expand Down Expand Up @@ -111,6 +111,18 @@ func TestLoadConfig(t *testing.T) {
},
},
},
{
id: component.NewIDWithName(metadata.Type, "9"),
expected: &Config{
ClusterURI: "https://CLUSTER.kusto.windows.net",
Database: "oteldb",
MetricTable: "OTELMetrics",
LogTable: "OTELLogs",
TraceTable: "OTELTraces",
UseDefaultAuth: true,
IngestionType: queuedIngestTest,
},
},
}

for _, tt := range tests {
Expand Down
7 changes: 6 additions & 1 deletion exporter/azuredataexplorerexporter/testdata/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,9 @@ azuredataexplorer/8:
enabled: true
initial_interval: 10s
max_interval: 60s
max_elapsed_time: 10m
max_elapsed_time: 10m
azuredataexplorer/9:
# Kusto cluster uri
cluster_uri: "https://CLUSTER.kusto.windows.net"
# weather to use the default azure auth
use_default_auth: true