GhostInThePotato
GhostInThePotato

Reputation: 51

Grafana role assignment using Azure AD OAuth

I'm trying to assign the Admin role in Grafana for certain user groups using Azure AD OAuth.

I can successfully log in with Azure AD credentials using this documentation: Set up OAuth2 with Azure Active Directory

According to this page I need to include role_attribute_path somewhere: Role mapping

role_attribute_path = contains(info.groups[*], 'admin') && 'Admin' || contains(info.groups[*], 'editor') && 'Editor' || 'Viewer'

Has anyone got a working example of role assignment using the Azure AD log in?

Upvotes: 2

Views: 6342

Answers (2)

GhostInThePotato
GhostInThePotato

Reputation: 51

With the introduction of Grafana 6.6.0, role assignment using OAuth with Azure AD is now possible.

I put the following into the config ini file to assign the Admin role to anyone in a certain Azure AD group and everyone else would become a Viewer:

    [auth.generic_oauth]
    name = Azure AD
    enabled = true
    allow_sign_up = true
    client_id = {{ .azure.client.id }}
    client_secret = {{ .azure.client.secret }}
    scopes = openid email profile
    auth_url = https://login.microsoftonline.com/{{ .azure.tenantid }}/oauth2/authorize
    token_url = https://login.microsoftonline.com/{{ .azure.tenantid }}/oauth2/token
    api_url =
    team_ids =
    allowed_organizations =
    role_attribute_path = contains(groups[*], '{{ .azure.admin_group }}') && 'Admin' || 'Viewer'

where

{{ .azure.client.id}} is the Azure AD, App registration, Application client ID

{{ .azure.client.secret}} is the client secret associated with the above registered app

{{ .azure.tenantid }} is the Azure AD tenant ID

{{ .azure.admin_group }} is the ObjectID of the Azure AD group you want as Admin roles

Upvotes: 3

fifofonix
fifofonix

Reputation: 361

I've just got this to work with Keycloak as my OIDC provider. This required trapping the response from the UserInfo OAuth2 endpoint and examining the resulting JSON. Only then are you going to be able to modify the JMESPath expression to achieve what you want.

To trap the response I had to make two curl calls and therefore you will likely need to do something similar for AzureAD. The first gets you an access token, and the second call uses this to get you the details you want - ie. groups/roles - that you have chosen to expose - from the UserInfo endpoint. This behavior is described in the Grafana docs.

For what it is worth for Keycloak the calls were on Linux/bash:

ACCESS_TOKEN=$(curl \
    -d "client_id=xxxx" \
    -d "client_secret=xxxx" \
    -d "username=xxxx" \
    -d "password=xxxx" \
    -d "grant_type=password" \
    "https://xxx.foo.bar/auth/realms/myrealm/protocol/openid-connect/token" \
        | jq --raw-output .access_token)

curl \
    -X POST \
    -H "Authorization: bearer "$ACCESS_TOKEN \
    "https://xxx.foo.bar/auth/realms/myrealm/protocol/openid-connect/userinfo" \
        | jq

When I managed to do this I found that I hadn't properly exposed the groups I was interested in and so needed to do some more config within Keycloak to enable this.

Through this tinkering I eventually got a JSON document with the groups key. Something like this:

{
  ...
  "groups": [
    "MyGroup"
  ],
  ...
}

At this point I could see that my JMESPath should therefore be:

contains(groups[*], 'MyGroup') && 'Admin'

Addendum

If you use multiple organizations in Grafana, and are migrating from LDAP, you may find that your next question is how can you map users to an org_id in a similar rules-based fashion.

As of Grafana 6.5.1 this feature is not supported although it has been requested as an enhancement. Nor is it possible to concurrently maintain a separate LDAP bind solely for the purpose of group lookups and org mappings UNLESS you are using an Oauth proxy configuration (Documentation regarding the possibility of using Oauth for authentication and LDAP for authorization with some sample configs here.)

Upvotes: 3

Related Questions