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

Support user-auth service principal #68

Merged
merged 18 commits into from
Feb 23, 2024
Merged

Conversation

aangelisc
Copy link
Contributor

@aangelisc aangelisc commented Nov 28, 2023

This PR updates the SDK to support a service principal credential when using user-authentication methods. This will allow us to support backend functionality via the service principal credentials which will always be present.

Changes:

  • ServiceCredentials and ServiceCredentialsEnabled properties added to current user credentials struct
  • Added UserIdentityFallbackCredentialsEnabled setting. Enabling this will allow users to specify fallback credentials when creating user identity data sources. This defaults to true.
  • Added support to user identity auth allowing MSI, Workload Identity, and App Registration credentials to be used as fallback when enabled.
  • Added helper functions to determine if a request has been initiated by the Grafana backend, and if the user initiating a request is authenticated with Azure AD.
  • Updated CurrentUserContext struct and request functions to appropriately set GrafanaIdToken
  • Added sufficient testing

It should be noted that for backend requests to be identified accurately the feature toggle idForwarding should be enabled.

Part of grafana/grafana#81918

Fixes #122

- If no user present OR no ID token AND usernameAssertion is disallowed
- Update tests
@kostrse
Copy link
Collaborator

kostrse commented Nov 29, 2023

We need to have design discussion regarding this

Copy link
Collaborator

@kostrse kostrse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AzureSeetings need a new switch to allow/disallow usage of the service credentials.

I would move the fallback logic directly into the user token provider. It needs to be redesigned somehow. Probably should contain an instance of service token provider internally and delegate access token request to it. e.g. work as a composite token provider (a decorator).

@@ -14,6 +14,7 @@ type AzureCredentials interface {

// AadCurrentUserCredentials "Current User" user identity credentials of the current Grafana user.
type AadCurrentUserCredentials struct {
ServicePrincipal AzureClientSecretCredentials
Copy link
Collaborator

@kostrse kostrse Jan 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Maybe let's we call it 'ServiceCredentials' to not introduce new terminology?
  2. Let's not limit it to AzureClientSecretCredentials, since there's no functional difference between which type of credentials is going to be used as long as it's service credentials. I would not bother to define new type hierarchy for "service" credentials specifically. Would just use "AzureCredentials" and have runtime check that they are not user identity.
  3. It should be optional, I think it needs to be a pointer (or once it's changed to interface AzureCredentials it will be fine).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made changes here that should meet the requirements.

@@ -71,6 +71,14 @@ func NewAzureAccessTokenProvider(settings *azsettings.AzureSettings, credentials
err = fmt.Errorf("user identity authentication is not enabled in Grafana config")
return nil, err
}

var tokenRetriever TokenRetriever
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather move the logic upper, before the switch (line 34) and wrote something like this (pseudocode):

nonUserContext = <determine from user context>  // i.e. not user initiated, no user context
if isUserIdentityCredentials(*credentials) && nonUserContext {
   if credentials.ServiceCredentials != nils {
       credentials = credentials.ServiceCredentials
   } else {
       error = "Attempt to user user credentials in non-user context"
   }
}

Copy link
Collaborator

@kostrse kostrse Jan 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OBO is also user identity authentication

Copy link
Collaborator

@kostrse kostrse Jan 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I see, user context isn't available in NewAzureAccessTokenProvider. It needs to be done inside userTokenProvider. userTokenProvider can be a decorator for service token provider.

@aangelisc aangelisc added enhancement New feature or request effort/medium and removed effort/small labels Feb 12, 2024
azsettings/env.go Outdated Show resolved Hide resolved
azsettings/settings.go Outdated Show resolved Hide resolved
kostrse
kostrse previously approved these changes Feb 20, 2024
@aangelisc aangelisc merged commit 3dc3da5 into main Feb 23, 2024
3 checks passed
@aangelisc aangelisc deleted the andreas/user-auth-backend branch February 23, 2024 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/medium enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support service principal for user-auth
4 participants