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

Cherry-pick #21044 to 7.x: Add support for different Azure Cloud environments in the metricbeat azure module #22262

Merged
merged 1 commit into from
Oct 30, 2020
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
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ field. You can revert this change by configuring tags for the module and omittin
- Release all kubernetes `state` metricsets as GA {pull}20901[20901]
- Move `compute_vm_scaleset` to light metricset. {pull}21038[21038] {issue}20985[20985]
- Sanitize `event.host`. {pull}21022[21022]
- Add support for different Azure Cloud environments in the metricbeat azure module. {pull}21044[21044] {issue}20988[20988]
- Add overview and platform health dashboards to Cloud Foundry module. {pull}21124[21124]
- Release lambda metricset in aws module as GA. {issue}21251[21251] {pull}21255[21255]
- Add dashboard for pubsub metricset in googlecloud module. {pull}21326[21326] {issue}17137[17137]
Expand Down
21 changes: 20 additions & 1 deletion metricbeat/docs/modules/azure.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,26 @@ Required credentials for the `azure` module:
`tenant_id`:: The unique identifier of the Azure Active Directory instance


Users can use the azure credentials keys if configured `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`
The azure credentials keys can be used if configured `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`

`resource_manager_endpoint` ::
_string_
Optional, by default the azure public environment will be used, to override, users can provide a specific resource manager endpoint in order to use a different azure environment.
Ex:
https://management.chinacloudapi.cn for azure ChinaCloud
https://management.microsoftazure.de for azure GermanCloud
https://management.azure.com for azure PublicCloud
https://management.usgovcloudapi.net for azure USGovernmentCloud

`active_directory_endpoint` ::
_string_
Optional, by default the associated active directory endpoint to the resource manager endpoint will be used, to override, users can provide a specific active directory endpoint in order to use a different azure environment.
Ex:
https://login.microsoftonline.com for azure ChinaCloud
https://login.microsoftonline.us for azure GermanCloud
https://login.chinacloudapi.cn for azure PublicCloud
https://login.microsoftonline.de for azure USGovernmentCloud


[float]
== Metricsets
Expand Down
21 changes: 20 additions & 1 deletion x-pack/metricbeat/module/azure/_meta/docs.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,26 @@ Required credentials for the `azure` module:
`tenant_id`:: The unique identifier of the Azure Active Directory instance


Users can use the azure credentials keys if configured `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`
The azure credentials keys can be used if configured `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`

`resource_manager_endpoint` ::
_string_
Optional, by default the azure public environment will be used, to override, users can provide a specific resource manager endpoint in order to use a different azure environment.
Ex:
https://management.chinacloudapi.cn for azure ChinaCloud
https://management.microsoftazure.de for azure GermanCloud
https://management.azure.com for azure PublicCloud
https://management.usgovcloudapi.net for azure USGovernmentCloud

`active_directory_endpoint` ::
_string_
Optional, by default the associated active directory endpoint to the resource manager endpoint will be used, to override, users can provide a specific active directory endpoint in order to use a different azure environment.
Ex:
https://login.microsoftonline.com for azure ChinaCloud
https://login.microsoftonline.us for azure GermanCloud
https://login.chinacloudapi.cn for azure PublicCloud
https://login.microsoftonline.de for azure USGovernmentCloud


[float]
== Metricsets
Expand Down
15 changes: 3 additions & 12 deletions x-pack/metricbeat/module/azure/billing/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
package billing

import (
"time"

"github.com/pkg/errors"

"github.com/elastic/beats/v7/x-pack/metricbeat/module/azure"

"github.com/elastic/beats/v7/libbeat/logp"
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/elastic/beats/v7/metricbeat/mb/parse"
Expand All @@ -32,19 +32,10 @@ type MetricSet struct {
log *logp.Logger
}

// Config options
type Config struct {
ClientId string `config:"client_id" validate:"required"`
ClientSecret string `config:"client_secret" validate:"required"`
TenantId string `config:"tenant_id" validate:"required"`
SubscriptionId string `config:"subscription_id" validate:"required"`
Period time.Duration `config:"period" validate:"nonzero,required"`
}

// New creates a new instance of the MetricSet. New is responsible for unpacking
// any MetricSet specific configuration options if there are any.
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
var config Config
var config azure.Config
err := base.Module().UnpackConfig(&config)
if err != nil {
return nil, errors.Wrap(err, "error unpack raw module config using UnpackConfig")
Expand Down
8 changes: 5 additions & 3 deletions x-pack/metricbeat/module/azure/billing/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"fmt"
"time"

"github.com/elastic/beats/v7/x-pack/metricbeat/module/azure"

"github.com/pkg/errors"

"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-01-01/consumption"
Expand All @@ -18,7 +20,7 @@ import (
// Client represents the azure client which will make use of the azure sdk go metrics related clients
type Client struct {
BillingService Service
Config Config
Config azure.Config
Log *logp.Logger
}

Expand All @@ -29,8 +31,8 @@ type Usage struct {
}

// NewClient instantiates the an Azure monitoring client
func NewClient(config Config) (*Client, error) {
usageService, err := NewService(config.ClientId, config.ClientSecret, config.TenantId, config.SubscriptionId)
func NewClient(config azure.Config) (*Client, error) {
usageService, err := NewService(config)
if err != nil {
return nil, err
}
Expand Down
4 changes: 3 additions & 1 deletion x-pack/metricbeat/module/azure/billing/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import (
"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-01-01/consumption"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"github.com/elastic/beats/v7/x-pack/metricbeat/module/azure"
)

var (
config = Config{}
config = azure.Config{}
)

func TestClient(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion x-pack/metricbeat/module/azure/billing/mock_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package billing
import (
"github.com/stretchr/testify/mock"

"github.com/elastic/beats/v7/x-pack/metricbeat/module/azure"

"github.com/elastic/beats/v7/libbeat/logp"

"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-01-01/consumption"
Expand All @@ -27,7 +29,7 @@ type MockService struct {
func NewMockClient() *Client {
return &Client{
new(MockService),
Config{},
azure.Config{},
logp.NewLogger("test azure monitor"),
}
}
Expand Down
12 changes: 8 additions & 4 deletions x-pack/metricbeat/module/azure/billing/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package billing
import (
"context"

"github.com/elastic/beats/v7/x-pack/metricbeat/module/azure"

"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-01-01/consumption"
"github.com/Azure/go-autorest/autorest/azure/auth"

Expand All @@ -22,14 +24,16 @@ type UsageService struct {
}

// NewService instantiates the Azure monitoring service
func NewService(clientId string, clientSecret string, tenantId string, subscriptionId string) (*UsageService, error) {
clientConfig := auth.NewClientCredentialsConfig(clientId, clientSecret, tenantId)
func NewService(config azure.Config) (*UsageService, error) {
clientConfig := auth.NewClientCredentialsConfig(config.ClientId, config.ClientSecret, config.TenantId)
clientConfig.AADEndpoint = config.ActiveDirectoryEndpoint
clientConfig.Resource = config.ResourceManagerEndpoint
authorizer, err := clientConfig.Authorizer()
if err != nil {
return nil, err
}
forcastsClient := consumption.NewForecastsClient(subscriptionId)
usageDetailsClient := consumption.NewUsageDetailsClient(subscriptionId)
forcastsClient := consumption.NewForecastsClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
usageDetailsClient := consumption.NewUsageDetailsClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
forcastsClient.Authorizer = authorizer
usageDetailsClient.Authorizer = authorizer
service := &UsageService{
Expand Down
2 changes: 1 addition & 1 deletion x-pack/metricbeat/module/azure/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type mapResourceMetrics func(client *Client, resources []resources.GenericResour

// NewClient instantiates the an Azure monitoring client
func NewClient(config Config) (*Client, error) {
azureMonitorService, err := NewService(config.ClientId, config.ClientSecret, config.TenantId, config.SubscriptionId)
azureMonitorService, err := NewService(config)
if err != nil {
return nil, err
}
Expand Down
63 changes: 44 additions & 19 deletions x-pack/metricbeat/module/azure/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,38 @@ package azure
import (
"time"

"github.com/elastic/beats/v7/libbeat/common"

"github.com/pkg/errors"
)

const (
// DefaultBaseURI is the default URI used for the service Insights
DefaultBaseURI = "https://management.azure.com/"
)

var (
AzureEnvs = common.MapStr{
"https://management.azure.com/": "https://login.microsoftonline.com/",
"https://management.usgovcloudapi.net/": "https://login.microsoftonline.us/",
"https://management.chinacloudapi.cn/": "https://login.chinacloudapi.cn/",
"https://management.microsoftazure.de/": "https://login.microsoftonline.de/",
}
)

// Config options
type Config struct {
ClientId string `config:"client_id"`
ClientSecret string `config:"client_secret"`
TenantId string `config:"tenant_id"`
SubscriptionId string `config:"subscription_id"`
Period time.Duration `config:"period" validate:"nonzero,required"`
Resources []ResourceConfig `config:"resources"`
RefreshListInterval time.Duration `config:"refresh_list_interval"`
DefaultResourceType string `config:"default_resource_type"`
AddCloudMetadata bool `config:"add_cloud_metadata"`
ClientId string `config:"client_id" validate:"required"`
ClientSecret string `config:"client_secret" validate:"required"`
TenantId string `config:"tenant_id" validate:"required"`
SubscriptionId string `config:"subscription_id" validate:"required"`
Period time.Duration `config:"period" validate:"nonzero,required"`
Resources []ResourceConfig `config:"resources"`
RefreshListInterval time.Duration `config:"refresh_list_interval"`
DefaultResourceType string `config:"default_resource_type"`
AddCloudMetadata bool `config:"add_cloud_metadata"`
ResourceManagerEndpoint string `config:"resource_manager_endpoint"`
ActiveDirectoryEndpoint string `config:"active_directory_endpoint"`
}

// ResourceConfig contains resource and metric list specific configuration.
Expand Down Expand Up @@ -52,17 +70,24 @@ type DimensionConfig struct {
}

func (conf *Config) Validate() error {
if conf.SubscriptionId == "" {
return errors.New("no subscription ID has been configured")
}
if conf.ClientSecret == "" {
return errors.New("no client secret has been configured")
}
if conf.ClientId == "" {
return errors.New("no client ID has been configured")
if conf.ResourceManagerEndpoint == "" {
conf.ResourceManagerEndpoint = DefaultBaseURI
}
if conf.TenantId == "" {
return errors.New("no tenant ID has been configured")
if conf.ActiveDirectoryEndpoint == "" {
ok, err := AzureEnvs.HasKey(conf.ResourceManagerEndpoint)
if err != nil {
return errors.Wrap(err, "No active directory endpoint found for the resource manager endpoint selected.")
}
if ok {
add, err := AzureEnvs.GetValue(conf.ResourceManagerEndpoint)
if err != nil {
return errors.Wrap(err, "No active directory endpoint found for the resource manager endpoint selected.")
}
conf.ActiveDirectoryEndpoint = add.(string)
}
if conf.ActiveDirectoryEndpoint == "" {
return errors.New("no active directory endpoint has been configured")
}
}
return nil
}
14 changes: 8 additions & 6 deletions x-pack/metricbeat/module/azure/monitor_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,18 @@ type MonitorService struct {
const metricNameLimit = 20

// NewService instantiates the Azure monitoring service
func NewService(clientId string, clientSecret string, tenantId string, subscriptionId string) (*MonitorService, error) {
clientConfig := auth.NewClientCredentialsConfig(clientId, clientSecret, tenantId)
func NewService(config Config) (*MonitorService, error) {
clientConfig := auth.NewClientCredentialsConfig(config.ClientId, config.ClientSecret, config.TenantId)
clientConfig.AADEndpoint = config.ActiveDirectoryEndpoint
clientConfig.Resource = config.ResourceManagerEndpoint
authorizer, err := clientConfig.Authorizer()
if err != nil {
return nil, err
}
metricsClient := insights.NewMetricsClient(subscriptionId)
metricsDefinitionClient := insights.NewMetricDefinitionsClient(subscriptionId)
resourceClient := resources.NewClient(subscriptionId)
metricNamespaceClient := insights.NewMetricNamespacesClient(subscriptionId)
metricsClient := insights.NewMetricsClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
metricsDefinitionClient := insights.NewMetricDefinitionsClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
resourceClient := resources.NewClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
metricNamespaceClient := insights.NewMetricNamespacesClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionId)
metricsClient.Authorizer = authorizer
metricsDefinitionClient.Authorizer = authorizer
resourceClient.Authorizer = authorizer
Expand Down