Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions plugins/inputs/azure_monitor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ plugin ordering. See [CONFIGURATION.md][CONFIGURATION.md] for more details.

[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins

## Secret-store support

This plugin supports secrets from secret-stores for the `client_secret` option.
See the [secret-store documentation][SECRETSTORE] for more details on how
to use them.

[SECRETSTORE]: ../../../docs/CONFIGURATION.md#secret-store-secrets

## Configuration

```toml @sample.conf
Expand All @@ -74,6 +82,7 @@ plugin ordering. See [CONFIGURATION.md][CONFIGURATION.md] for more details.
# - Managed Identity
# - Azure CLI auth
# - Developer Azure CLI auth
# Supports referencing values from secret stores using @{<store>:<key>} syntax
client_secret = "<<CLIENT_SECRET>>"
# can be found under Azure Active Directory->Properties
tenant_id = "<<TENANT_ID>>"
Expand Down
26 changes: 24 additions & 2 deletions plugins/inputs/azure_monitor/azure_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package azure_monitor

import (
_ "embed"
"errors"
"fmt"
"sync"

Expand All @@ -12,13 +13,14 @@ import (
receiver "github.com/logzio/azure-monitor-metrics-receiver"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/inputs"
)

type AzureMonitor struct {
SubscriptionID string `toml:"subscription_id"`
ClientID string `toml:"client_id"`
ClientSecret string `toml:"client_secret"`
ClientSecret config.Secret `toml:"client_secret"`
Comment thread
skartikey marked this conversation as resolved.
TenantID string `toml:"tenant_id"`
CloudOption string `toml:"cloud_option,omitempty"`
ResourceTargets []*resourceTarget `toml:"resource_target"`
Expand Down Expand Up @@ -63,6 +65,10 @@ func (*AzureMonitor) SampleConfig() string {
}

func (am *AzureMonitor) Init() error {
if am.SubscriptionID == "" {
return errors.New("subscription_id is required")
}

var clientOptions azcore.ClientOptions
switch am.CloudOption {
case "AzureChina":
Expand All @@ -75,8 +81,24 @@ func (am *AzureMonitor) Init() error {
return fmt.Errorf("unknown cloud option: %s", am.CloudOption)
}

var clientSecret string
if !am.ClientSecret.Empty() {
if am.ClientID == "" {
return errors.New("client_id is required when client_secret is set")
}
if am.TenantID == "" {
return errors.New("tenant_id is required when client_secret is set")
}
secret, err := am.ClientSecret.Get()
if err != nil {
return fmt.Errorf("getting client secret failed: %w", err)
}
clientSecret = secret.String()
secret.Destroy()
}

var err error
am.azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions)
am.azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, clientSecret, am.TenantID, clientOptions)
if err != nil {
return err
}
Expand Down
124 changes: 41 additions & 83 deletions plugins/inputs/azure_monitor/azure_monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
"github.com/influxdata/toml"
Expand Down Expand Up @@ -116,23 +115,23 @@ func (*mockAzureMetricDefinitionsClient) List(
return armmonitor.MetricDefinitionsClientListResponse{}, err
}

if resourceID == "/subscriptions/subscriptionID/resourceGroups/resourceGroup1/providers/Microsoft.Test/type1/resource1" {
switch resourceID {
case "/subscriptions/subscriptionID/resourceGroups/resourceGroup1/providers/Microsoft.Test/type1/resource1":
return armmonitor.MetricDefinitionsClientListResponse{
MetricDefinitionCollection: armmonitor.MetricDefinitionCollection{
Value: metricDefinitions[0],
},
}, nil
}

if resourceID == "/subscriptions/subscriptionID/resourceGroups/resourceGroup1/providers/Microsoft.Test/type2/resource2" {
case "/subscriptions/subscriptionID/resourceGroups/resourceGroup1/providers/Microsoft.Test/type2/resource2",
"/subscriptions/subscriptionID/resourceGroups/resourceGroup2/providers/Microsoft.Test/type2/resource4",
"/subscriptions/subscriptionID/resourceGroups/resourceGroup2/providers/Microsoft.Test/type2/resource5",
"/subscriptions/subscriptionID/resourceGroups/resourceGroup2/providers/Microsoft.Test/type2/resource6":
return armmonitor.MetricDefinitionsClientListResponse{
MetricDefinitionCollection: armmonitor.MetricDefinitionCollection{
Value: metricDefinitions[1],
},
}, nil
}

if resourceID == "/subscriptions/subscriptionID/resourceGroups/resourceGroup2/providers/Microsoft.Test/type1/resource3" {
case "/subscriptions/subscriptionID/resourceGroups/resourceGroup2/providers/Microsoft.Test/type1/resource3":
return armmonitor.MetricDefinitionsClientListResponse{
MetricDefinitionCollection: armmonitor.MetricDefinitionCollection{
Value: metricDefinitions[2],
Expand Down Expand Up @@ -611,6 +610,36 @@ func TestInit_NoSubscriptionID(t *testing.T) {
require.Error(t, am.Init())
}

func TestInit_NoClientID(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_client_id.toml")
require.NoError(t, err)
require.NotNil(t, file)
require.NotEmpty(t, file)

var am *AzureMonitor
require.NoError(t, toml.Unmarshal(file, &am))

am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}

require.Error(t, am.Init())
}

func TestInit_NoTenantID(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_tenant_id.toml")
require.NoError(t, err)
require.NotNil(t, file)
require.NotEmpty(t, file)

var am *AzureMonitor
require.NoError(t, toml.Unmarshal(file, &am))

am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}

require.Error(t, am.Init())
}

func TestInit_NoTargets(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_targets.toml")
require.NoError(t, err)
Expand Down Expand Up @@ -906,25 +935,8 @@ func TestGather_Success(t *testing.T) {

am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}
resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets))
for _, target := range am.ResourceTargets {
resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations))
}

var clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic}

var azureClients *receiver.AzureClients
azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions)
require.NoError(t, err)
require.NotNil(t, azureClients)

am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(
am.SubscriptionID,
receiver.NewTargets(resourceTargets, nil, nil),
azureClients,
)
require.NoError(t, err)
require.NotNil(t, am.receiver)
require.NoError(t, am.Init())

expectedResource1Metric1Name := "azure_monitor_microsoft_test_type1_metric1"
expectedResource1Metric1MetricFields := make(map[string]interface{})
Expand Down Expand Up @@ -993,25 +1005,7 @@ func TestGather_China_Success(t *testing.T) {
am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}

resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets))
for _, target := range am.ResourceTargets {
resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations))
}

var clientOptions = azcore.ClientOptions{Cloud: cloud.AzureChina}

var azureClients *receiver.AzureClients
azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions)
require.NoError(t, err)
require.NotNil(t, azureClients)

am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(
am.SubscriptionID,
receiver.NewTargets(resourceTargets, nil, nil),
azureClients,
)
require.NoError(t, err)
require.NotNil(t, am.receiver)
require.NoError(t, am.Init())
}

func TestGather_Government_Success(t *testing.T) {
Expand All @@ -1026,25 +1020,7 @@ func TestGather_Government_Success(t *testing.T) {
am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}

resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets))
for _, target := range am.ResourceTargets {
resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations))
}

var clientOptions = azcore.ClientOptions{Cloud: cloud.AzureGovernment}

var azureClients *receiver.AzureClients
azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions)
require.NoError(t, err)
require.NotNil(t, azureClients)

am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(
am.SubscriptionID,
receiver.NewTargets(resourceTargets, nil, nil),
azureClients,
)
require.NoError(t, err)
require.NotNil(t, am.receiver)
require.NoError(t, am.Init())
}

func TestGather_Public_Success(t *testing.T) {
Expand All @@ -1059,23 +1035,5 @@ func TestGather_Public_Success(t *testing.T) {
am.Log = testutil.Logger{}
am.azureManager = &mockAzureClientsManager{}

resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets))
for _, target := range am.ResourceTargets {
resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations))
}

var clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic}

var azureClients *receiver.AzureClients
azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions)
require.NoError(t, err)
require.NotNil(t, azureClients)

am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(
am.SubscriptionID,
receiver.NewTargets(resourceTargets, nil, nil),
azureClients,
)
require.NoError(t, err)
require.NotNil(t, am.receiver)
require.NoError(t, am.Init())
}
1 change: 1 addition & 0 deletions plugins/inputs/azure_monitor/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# - Managed Identity
# - Azure CLI auth
# - Developer Azure CLI auth
# Supports referencing values from secret stores using @{<store>:<key>} syntax
client_secret = "<<CLIENT_SECRET>>"
# can be found under Azure Active Directory->Properties
tenant_id = "<<TENANT_ID>>"
Expand Down
Loading