Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
alyssabull authored Feb 3, 2025
2 parents f0bcf34 + 85ebb9a commit ff8fa64
Show file tree
Hide file tree
Showing 13 changed files with 567 additions and 267 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Change Log

## v2.1.2

- Dependency updates
- Fix bug where `AzureAuthEnabled` setting was not correctly picked up from context

## v2.1.1

- Dependency updates

## v2.1.0

- Add Azure Entra Password as a credentials type. This is not a recommended authentication method and is currently only supported for MSSQL. If you require this method the token provider will need to be implemented separately.

## v2.0.0

- **Breaking change:** `mapUtil` is removed [#106](https://github.com/grafana/grafana-azure-sdk-go/pull/106). `mapUtil` functions moved to
Expand Down
19 changes: 19 additions & 0 deletions azcredentials/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,26 @@ func getFromCredentialsObject(credentialsObj map[string]interface{}, secureData
},
}
return credentials, nil
case AzureAuthEntraPasswordCredentials:
userId, err := maputil.GetString(credentialsObj, "userId")
if err != nil {
return nil, err
}
clientId, err := maputil.GetString(credentialsObj, "clientId")
if err != nil {
return nil, err
}
password, ok := secureData["password"]
if !ok {
return nil, fmt.Errorf("no password provided")
}

credentials := &AzureEntraPasswordCredentials{
Password: password,
UserId: userId,
ClientId: clientId,
}
return credentials, nil
default:
err := fmt.Errorf("the authentication type '%s' not supported", authType)
return nil, err
Expand Down
2 changes: 2 additions & 0 deletions azcredentials/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func GetAzureCloud(settings *azsettings.AzureSettings, credentials AzureCredenti
return c.AzureCloud, nil
case *AzureClientSecretOboCredentials:
return c.ClientSecretCredentials.AzureCloud, nil
case *AzureEntraPasswordCredentials:
return settings.GetDefaultCloud(), nil
default:
err := fmt.Errorf("the Azure credentials of type '%s' not supported", c.AzureAuthType())
return "", err
Expand Down
22 changes: 17 additions & 5 deletions azcredentials/credentials.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package azcredentials

const (
AzureAuthCurrentUserIdentity = "currentuser"
AzureAuthManagedIdentity = "msi"
AzureAuthWorkloadIdentity = "workloadidentity"
AzureAuthClientSecret = "clientsecret"
AzureAuthClientSecretObo = "clientsecret-obo"
AzureAuthCurrentUserIdentity = "currentuser"
AzureAuthManagedIdentity = "msi"
AzureAuthWorkloadIdentity = "workloadidentity"
AzureAuthClientSecret = "clientsecret"
AzureAuthClientSecretObo = "clientsecret-obo"
AzureAuthEntraPasswordCredentials = "ad-password"
)

type AzureCredentials interface {
Expand Down Expand Up @@ -39,6 +40,13 @@ type AzureClientSecretCredentials struct {
ClientSecret string
}

type AzureEntraPasswordCredentials struct {
Password string
UserId string
ClientId string
TenantId string
}

// AzureClientSecretOboCredentials "App Registration (On-Behalf-Of)" user identity credentials obtained using
// service identity configured in the datasource.
type AzureClientSecretOboCredentials struct {
Expand All @@ -64,3 +72,7 @@ func (credentials *AzureClientSecretCredentials) AzureAuthType() string {
func (credentials *AzureClientSecretOboCredentials) AzureAuthType() string {
return AzureAuthClientSecretObo
}

func (credentials *AzureEntraPasswordCredentials) AzureAuthType() string {
return AzureAuthEntraPasswordCredentials
}
3 changes: 3 additions & 0 deletions azsettings/cloud_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var predefinedClouds = []*AzureCloudSettings{
"portal": "https://portal.azure.com",
"prometheusResourceId": "https://prometheus.monitor.azure.com",
"resourceManager": "https://management.azure.com",
"ossrdbmsResourceId": "https://ossrdbms-aad.database.windows.net",
},
},
{
Expand All @@ -40,6 +41,7 @@ var predefinedClouds = []*AzureCloudSettings{
"portal": "https://portal.azure.cn",
"prometheusResourceId": "https://prometheus.monitor.azure.cn",
"resourceManager": "https://management.chinacloudapi.cn",
"ossrdbmsResourceId": "https://ossrdbms-aad.database.chinacloudapi.cn",
},
},
{
Expand All @@ -52,6 +54,7 @@ var predefinedClouds = []*AzureCloudSettings{
"portal": "https://portal.azure.us",
"prometheusResourceId": "https://prometheus.monitor.azure.us",
"resourceManager": "https://management.usgovcloudapi.net",
"ossrdbmsResourceId": "https://ossrdbms-aad.database.usgovcloudapi.net",
},
},
}
Expand Down
52 changes: 42 additions & 10 deletions azsettings/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ const (
WorkloadIdentityClientID = "GFAZPL_WORKLOAD_IDENTITY_CLIENT_ID"
WorkloadIdentityTokenFile = "GFAZPL_WORKLOAD_IDENTITY_TOKEN_FILE"

UserIdentityEnabled = "GFAZPL_USER_IDENTITY_ENABLED"
UserIdentityTokenURL = "GFAZPL_USER_IDENTITY_TOKEN_URL"
UserIdentityClientID = "GFAZPL_USER_IDENTITY_CLIENT_ID"
UserIdentityClientSecret = "GFAZPL_USER_IDENTITY_CLIENT_SECRET"
UserIdentityAssertion = "GFAZPL_USER_IDENTITY_ASSERTION"
UserIdentityFallbackCredentialsEnabled = "GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED"
UserIdentityEnabled = "GFAZPL_USER_IDENTITY_ENABLED"
UserIdentityTokenURL = "GFAZPL_USER_IDENTITY_TOKEN_URL"
UserIdentityClientAuthentication = "GFAZPL_USER_IDENTITY_CLIENT_AUTHENTICATION"
UserIdentityClientID = "GFAZPL_USER_IDENTITY_CLIENT_ID"
UserIdentityClientSecret = "GFAZPL_USER_IDENTITY_CLIENT_SECRET"
UserIdentityManagedIdentityClientID = "GFAZPL_USER_IDENTITY_MANAGED_IDENTITY_CLIENT_ID"
UserIdentityFederatedCredentialAudience = "GFAZPL_USER_IDENTITY_FEDERATED_CREDENTIAL_AUDIENCE"
UserIdentityAssertion = "GFAZPL_USER_IDENTITY_ASSERTION"
UserIdentityFallbackCredentialsEnabled = "GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED"

AzureEntraPasswordCredentialsEnabled = "GFAZPL_AZURE_ENTRA_PASSWORD_CREDENTIALS_ENABLED"

// Pre Grafana 9.x variables
fallbackAzureCloud = "AZURE_CLOUD"
Expand Down Expand Up @@ -87,6 +92,9 @@ func ReadFromEnv() (*AzureSettings, error) {
return nil, err
}

// Default to client_secret_post if not set
clientAuthentication := envutil.GetOrDefault(UserIdentityClientAuthentication, "client_secret_post")

clientId, err := envutil.Get(UserIdentityClientID)
if err != nil {
err = fmt.Errorf("client ID must be set when user identity authentication enabled: %w", err)
Expand All @@ -95,6 +103,10 @@ func ReadFromEnv() (*AzureSettings, error) {

clientSecret := envutil.GetOrDefault(UserIdentityClientSecret, "")

managedIdentityClientId := envutil.GetOrDefault(UserIdentityManagedIdentityClientID, "")

federatedCredentialAudience := envutil.GetOrDefault(UserIdentityFederatedCredentialAudience, "")

assertion := envutil.GetOrDefault(UserIdentityAssertion, "")
usernameAssertion := assertion == "username"

Expand All @@ -105,14 +117,25 @@ func ReadFromEnv() (*AzureSettings, error) {

azureSettings.UserIdentityEnabled = true
azureSettings.UserIdentityTokenEndpoint = &TokenEndpointSettings{
TokenUrl: tokenUrl,
ClientId: clientId,
ClientSecret: clientSecret,
UsernameAssertion: usernameAssertion,
TokenUrl: tokenUrl,
ClientAuthentication: clientAuthentication,
ClientId: clientId,
ClientSecret: clientSecret,
ManagedIdentityClientId: managedIdentityClientId,
FederatedCredentialAudience: federatedCredentialAudience,
UsernameAssertion: usernameAssertion,
}
azureSettings.UserIdentityFallbackCredentialsEnabled = serviceCredentialsFallback
}

// Client Password Credentials auth
if AzureEntraPasswordCredentialsEnabled, err := envutil.GetBoolOrDefault(AzureEntraPasswordCredentialsEnabled, false); err != nil {
err = fmt.Errorf("invalid Azure configuration: %w", err)
return nil, err
} else {
azureSettings.AzureEntraPasswordCredentialsEnabled = AzureEntraPasswordCredentialsEnabled
}

return azureSettings, nil
}

Expand Down Expand Up @@ -160,12 +183,21 @@ func WriteToEnvStr(azureSettings *AzureSettings) []string {
if tokenEndpoint.TokenUrl != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityTokenURL, tokenEndpoint.TokenUrl))
}
if tokenEndpoint.ClientAuthentication != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityClientAuthentication, tokenEndpoint.ClientAuthentication))
}
if tokenEndpoint.ClientId != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityClientID, tokenEndpoint.ClientId))
}
if tokenEndpoint.ClientSecret != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityClientSecret, tokenEndpoint.ClientSecret))
}
if tokenEndpoint.ManagedIdentityClientId != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityManagedIdentityClientID, tokenEndpoint.ManagedIdentityClientId))
}
if tokenEndpoint.FederatedCredentialAudience != "" {
envs = append(envs, fmt.Sprintf("%s=%s", UserIdentityFederatedCredentialAudience, tokenEndpoint.FederatedCredentialAudience))
}
if tokenEndpoint.UsernameAssertion {
envs = append(envs, fmt.Sprintf("%s=username", UserIdentityAssertion))
}
Expand Down
Loading

0 comments on commit ff8fa64

Please sign in to comment.