Reputation: 51
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
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
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