discovery: add support for Managed Identity authentication in Azure SD (#4590)
Signed-off-by: Marcel Juhnke <marrat@marrat.de>
This commit is contained in:
parent
fb8479a677
commit
c7d83b2b6a
|
@ -444,13 +444,14 @@ var expectedConf = &Config{
|
||||||
ServiceDiscoveryConfig: sd_config.ServiceDiscoveryConfig{
|
ServiceDiscoveryConfig: sd_config.ServiceDiscoveryConfig{
|
||||||
AzureSDConfigs: []*azure.SDConfig{
|
AzureSDConfigs: []*azure.SDConfig{
|
||||||
{
|
{
|
||||||
Environment: "AzurePublicCloud",
|
Environment: "AzurePublicCloud",
|
||||||
SubscriptionID: "11AAAA11-A11A-111A-A111-1111A1111A11",
|
SubscriptionID: "11AAAA11-A11A-111A-A111-1111A1111A11",
|
||||||
TenantID: "BBBB222B-B2B2-2B22-B222-2BB2222BB2B2",
|
TenantID: "BBBB222B-B2B2-2B22-B222-2BB2222BB2B2",
|
||||||
ClientID: "333333CC-3C33-3333-CCC3-33C3CCCCC33C",
|
ClientID: "333333CC-3C33-3333-CCC3-33C3CCCCC33C",
|
||||||
ClientSecret: "mysecret",
|
ClientSecret: "mysecret",
|
||||||
RefreshInterval: model.Duration(5 * time.Minute),
|
AuthenticationMethod: "OAuth",
|
||||||
Port: 9100,
|
RefreshInterval: model.Duration(5 * time.Minute),
|
||||||
|
Port: 9100,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -769,6 +770,10 @@ var expectedErrors = []struct {
|
||||||
filename: "azure_tenant_id_missing.bad.yml",
|
filename: "azure_tenant_id_missing.bad.yml",
|
||||||
errMsg: "Azure SD configuration requires a tenant_id",
|
errMsg: "Azure SD configuration requires a tenant_id",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
filename: "azure_authentication_method.bad.yml",
|
||||||
|
errMsg: "Unknown authentication_type \"invalid\". Supported types are \"OAuth\" or \"ManagedIdentity\"",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
filename: "empty_scrape_config.bad.yml",
|
filename: "empty_scrape_config.bad.yml",
|
||||||
errMsg: "empty or null scrape config section",
|
errMsg: "empty or null scrape config section",
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
scrape_configs:
|
||||||
|
- azure_sd_configs:
|
||||||
|
- authentication_method: invalid
|
||||||
|
subscription_id: 11AAAA11-A11A-111A-A111-1111A1111A11
|
|
@ -196,6 +196,7 @@ scrape_configs:
|
||||||
- job_name: service-azure
|
- job_name: service-azure
|
||||||
azure_sd_configs:
|
azure_sd_configs:
|
||||||
- environment: AzurePublicCloud
|
- environment: AzurePublicCloud
|
||||||
|
authentication_method: OAuth
|
||||||
subscription_id: 11AAAA11-A11A-111A-A111-1111A1111A11
|
subscription_id: 11AAAA11-A11A-111A-A111-1111A1111A11
|
||||||
tenant_id: BBBB222B-B2B2-2B22-B222-2BB2222BB2B2
|
tenant_id: BBBB222B-B2B2-2B22-B222-2BB2222BB2B2
|
||||||
client_id: 333333CC-3C33-3333-CCC3-33C3CCCCC33C
|
client_id: 333333CC-3C33-3333-CCC3-33C3CCCCC33C
|
||||||
|
|
|
@ -26,13 +26,11 @@ import (
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
"github.com/Azure/go-autorest/autorest/adal"
|
"github.com/Azure/go-autorest/autorest/adal"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
"github.com/prometheus/prometheus/util/strutil"
|
"github.com/prometheus/prometheus/util/strutil"
|
||||||
)
|
)
|
||||||
|
@ -47,6 +45,9 @@ const (
|
||||||
azureLabelMachinePrivateIP = azureLabel + "machine_private_ip"
|
azureLabelMachinePrivateIP = azureLabel + "machine_private_ip"
|
||||||
azureLabelMachineTag = azureLabel + "machine_tag_"
|
azureLabelMachineTag = azureLabel + "machine_tag_"
|
||||||
azureLabelMachineScaleSet = azureLabel + "machine_scale_set"
|
azureLabelMachineScaleSet = azureLabel + "machine_scale_set"
|
||||||
|
|
||||||
|
authMethodOAuth = "OAuth"
|
||||||
|
authMethodManagedIdentity = "ManagedIdentity"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -63,21 +64,23 @@ var (
|
||||||
|
|
||||||
// DefaultSDConfig is the default Azure SD configuration.
|
// DefaultSDConfig is the default Azure SD configuration.
|
||||||
DefaultSDConfig = SDConfig{
|
DefaultSDConfig = SDConfig{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
RefreshInterval: model.Duration(5 * time.Minute),
|
RefreshInterval: model.Duration(5 * time.Minute),
|
||||||
Environment: azure.PublicCloud.Name,
|
Environment: azure.PublicCloud.Name,
|
||||||
|
AuthenticationMethod: authMethodOAuth,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// SDConfig is the configuration for Azure based service discovery.
|
// SDConfig is the configuration for Azure based service discovery.
|
||||||
type SDConfig struct {
|
type SDConfig struct {
|
||||||
Environment string `yaml:"environment,omitempty"`
|
Environment string `yaml:"environment,omitempty"`
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
SubscriptionID string `yaml:"subscription_id"`
|
SubscriptionID string `yaml:"subscription_id"`
|
||||||
TenantID string `yaml:"tenant_id,omitempty"`
|
TenantID string `yaml:"tenant_id,omitempty"`
|
||||||
ClientID string `yaml:"client_id,omitempty"`
|
ClientID string `yaml:"client_id,omitempty"`
|
||||||
ClientSecret config_util.Secret `yaml:"client_secret,omitempty"`
|
ClientSecret config_util.Secret `yaml:"client_secret,omitempty"`
|
||||||
RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"`
|
RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"`
|
||||||
|
AuthenticationMethod string `yaml:"authentication_method,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAuthParam(param, name string) error {
|
func validateAuthParam(param, name string) error {
|
||||||
|
@ -95,18 +98,27 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = validateAuthParam(c.SubscriptionID, "subscription_id"); err != nil {
|
if err = validateAuthParam(c.SubscriptionID, "subscription_id"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = validateAuthParam(c.TenantID, "tenant_id"); err != nil {
|
|
||||||
return err
|
if c.AuthenticationMethod == authMethodOAuth {
|
||||||
|
if err = validateAuthParam(c.TenantID, "tenant_id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = validateAuthParam(c.ClientID, "client_id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = validateAuthParam(string(c.ClientSecret), "client_secret"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err = validateAuthParam(c.ClientID, "client_id"); err != nil {
|
|
||||||
return err
|
if c.AuthenticationMethod != authMethodOAuth && c.AuthenticationMethod != authMethodManagedIdentity {
|
||||||
}
|
return fmt.Errorf("Unknown authentication_type %q. Supported types are %q or %q", c.AuthenticationMethod, authMethodOAuth, authMethodManagedIdentity)
|
||||||
if err = validateAuthParam(string(c.ClientSecret), "client_secret"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +198,30 @@ func createAzureClient(cfg SDConfig) (azureClient, error) {
|
||||||
resourceManagerEndpoint := env.ResourceManagerEndpoint
|
resourceManagerEndpoint := env.ResourceManagerEndpoint
|
||||||
|
|
||||||
var c azureClient
|
var c azureClient
|
||||||
oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, cfg.TenantID)
|
|
||||||
if err != nil {
|
var spt *adal.ServicePrincipalToken
|
||||||
return azureClient{}, err
|
|
||||||
}
|
switch cfg.AuthenticationMethod {
|
||||||
spt, err := adal.NewServicePrincipalToken(*oauthConfig, cfg.ClientID, string(cfg.ClientSecret), resourceManagerEndpoint)
|
case authMethodManagedIdentity:
|
||||||
if err != nil {
|
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
||||||
return azureClient{}, err
|
if err != nil {
|
||||||
|
return azureClient{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spt, err = adal.NewServicePrincipalTokenFromMSI(msiEndpoint, resourceManagerEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return azureClient{}, err
|
||||||
|
}
|
||||||
|
case authMethodOAuth:
|
||||||
|
oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, cfg.TenantID)
|
||||||
|
if err != nil {
|
||||||
|
return azureClient{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spt, err = adal.NewServicePrincipalToken(*oauthConfig, cfg.ClientID, string(cfg.ClientSecret), resourceManagerEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return azureClient{}, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bearerAuthorizer := autorest.NewBearerAuthorizer(spt)
|
bearerAuthorizer := autorest.NewBearerAuthorizer(spt)
|
||||||
|
|
|
@ -274,14 +274,18 @@ See below for the configuration options for Azure discovery:
|
||||||
# The information to access the Azure API.
|
# The information to access the Azure API.
|
||||||
# The Azure environment.
|
# The Azure environment.
|
||||||
[ environment: <string> | default = AzurePublicCloud ]
|
[ environment: <string> | default = AzurePublicCloud ]
|
||||||
# The subscription ID.
|
|
||||||
|
# The authentication method, either OAuth or ManagedIdentity.
|
||||||
|
# See https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
|
||||||
|
[ authentication_method: <string> | default = OAuth]
|
||||||
|
# The subscription ID. Always required.
|
||||||
subscription_id: <string>
|
subscription_id: <string>
|
||||||
# The tenant ID.
|
# Optional tenant ID. Only required with authentication_method OAuth.
|
||||||
tenant_id: <string>
|
[ tenant_id: <string> ]
|
||||||
# The client ID.
|
# Optional client ID. Only required with authentication_method OAuth.
|
||||||
client_id: <string>
|
[ client_id: <string> ]
|
||||||
# The client secret.
|
# Optional client secret. Only required with authentication_method OAuth.
|
||||||
client_secret: <secret>
|
[ client_secret: <secret> ]
|
||||||
|
|
||||||
# Refresh interval to re-read the instance list.
|
# Refresh interval to re-read the instance list.
|
||||||
[ refresh_interval: <duration> | default = 300s ]
|
[ refresh_interval: <duration> | default = 300s ]
|
||||||
|
|
Loading…
Reference in New Issue