Auth: Embedded OpenFGA authorization driver
Adds the embedded OpenFGA authorization driver for use with OIDC authentication. We will make this the default for TLS authenticated users when we are confident in its performance and reliability.
Implements https://discourse.ubuntu.com/t/identity-and-access-management-for-lxd/41516 with some changes. These will be updated in the spec. Completes https://warthogs.atlassian.net/browse/LXD-679
Warning: All users that currently authenticate to LXD with OIDC will lose access to their cluster. To regain access, a user must:
- Make a call to LXD (e.g.
lxc info) to ensure their OIDC identity has been added to the database. - Create a group
lxc auth group create my-group - Grant the group a suitable permission. As all current OIDC users are administrators, a suitable permission is "admin" on "server". This can be performed with
lxc auth group permission add my-group server admin. - Add themselves to the group. This can be performed with
lxc auth identity group add oidc/<email-address> my-group.
To perform steps 2-4, another authentication method must be used. This can be via an unrestricted TLS certificate or directly via the unix socket.
I'm not sure why this is failing the compatibility check:
- https://github.com/canonical/lxd/actions/runs/8071688009/job/22051847315?pr=12976#step:8:212
go: github.com/openfga/[email protected] requires [email protected], but 1.21 is requested
It's I'm using 1.21.7 locally.
I'm not sure why this is failing the compatibility check:
* https://github.com/canonical/lxd/actions/runs/8071688009/job/22051847315?pr=12976#step:8:212 * `go: github.com/openfga/[email protected] requires [email protected], but 1.21 is requested`It's I'm using 1.21.7 locally.
Think we need to switch that to use go get go@ call like the earlier PR https://github.com/canonical/lxd/blob/main/.github/workflows/tests.yml#L228
Can be rebased now.
Ready for rebase
I've rebased onto main. Hopefully this looks a lot less daunting to review now :laughing:
While testing I've come across this error: https://github.com/canonical/lxd/actions/runs/8083078860/job/22085325564?pr=12976#step:13:7250
The test isn't catching it but this was caused by the OpenFGA datastore trying to resolve the URL of a permission whose entity no longer existed.
I have a fix for this already but it's actually only a one-line change in the driver, the majority of the changes are in the permission API handlers and some already existing DB methods. I think for the sake of keeping this PR simple I will raise it as a separate PR and this PR can be rebased onto that one when merged. So for now I'm putting this back to draft status.
While testing I've come across this error: https://github.com/canonical/lxd/actions/runs/8083078860/job/22085325564?pr=12976#step:13:7250
The test isn't catching it but this was caused by the OpenFGA datastore trying to resolve the URL of a permission whose entity no longer existed.
I have a fix for this already but it's actually only a one-line change in the driver, the majority of the changes are in the permission API handlers and some already existing DB methods. I think for the sake of keeping this PR simple I will raise it as a separate PR and this PR can be rebased onto that one when merged. So for now I'm putting this back to draft status.
Once #12992 is merged I'll rebase and unmark as draft.
While testing I've come across this error: https://github.com/canonical/lxd/actions/runs/8083078860/job/22085325564?pr=12976#step:13:7250
The test isn't catching it but this was caused by the OpenFGA datastore trying to resolve the URL of a permission whose entity no longer existed.
I have a fix for this already but it's actually only a one-line change in the driver, the majority of the changes are in the permission API handlers and some already existing DB methods. I think for the sake of keeping this PR simple I will raise it as a separate PR and this PR can be rebased onto that one when merged. So for now I'm putting this back to draft status.
Once #12992 is merged I'll rebase and unmark as draft.
@markylaing as discussed, I will just leave this comment here regarding idp groups for future reference. So it was found that after an OIDC identity logs in, if its idp groups were successfully mapped via the custom claim, the identity gets assigned to the correct lxd groups and therefore gets the right permissions. However, when we query the API for group memberships, the association between the lxd groups and the identity is missing. It was mentioned for idp mapped groups, the relationship between those groups and the identity is not currently stored in the database, so we can't get that data.
@markylaing found another issue with the identity-provider-group endpoint. See below terminal output:
root@lxd-permissions-dev:~/lxd# lxc query /1.0/auth/groups
[
"/1.0/auth/groups/admin-group",
"/1.0/auth/groups/big-permission",
"/1.0/auth/groups/small-permission"
]
root@lxd-permissions-dev:~/lxd# lxc query /1.0/auth/identity-provider-groups/test?recursion=1
{
"groups": [],
"name": "test"
}
root@lxd-permissions-dev:~/lxd# lxc auth identity-provider-group group add test admin-group
Error: Failed to write identity provider group mappings: FOREIGN KEY constraint failed
For some reason trying to add lxd group to an idp group fails foreign key constraint. But using the same CLI command I was able to add a lxd group to the owner idp group. For some more context, see below table data for the relevant endpoints:
root@lxd-permissions-dev:~/lxd# lxd sql global "select * from auth_groups"
DEBUG [2024-03-01T15:14:29Z] Connecting to a local LXD over a Unix socket
DEBUG [2024-03-01T15:14:29Z] Sending request to LXD etag= method=POST url="http://unix.socket/internal/sql"
DEBUG [2024-03-01T15:14:29Z]
{
"database": "global",
"query": "select * from auth_groups"
}
+----+------------------+-------------+
| id | name | description |
+----+------------------+-------------+
| 1 | admin-group | |
| 8 | big-permission | |
| 9 | small-permission | |
+----+------------------+-------------+
root@lxd-permissions-dev:~/lxd# lxd sql global "select * from identity_provider_groups"
DEBUG [2024-03-01T15:14:36Z] Connecting to a local LXD over a Unix socket
DEBUG [2024-03-01T15:14:36Z] Sending request to LXD etag= method=POST url="http://unix.socket/internal/sql"
DEBUG [2024-03-01T15:14:36Z]
{
"database": "global",
"query": "select * from identity_provider_groups"
}
+----+-------+
| id | name |
+----+-------+
| 1 | owner |
| 5 | test |
+----+-------+
root@lxd-permissions-dev:~/lxd# lxd sql global "select * from auth_groups_identity_provider_groups"
DEBUG [2024-03-01T15:14:48Z] Connecting to a local LXD over a Unix socket
DEBUG [2024-03-01T15:14:48Z] Sending request to LXD etag= method=POST url="http://unix.socket/internal/sql"
DEBUG [2024-03-01T15:14:48Z]
{
"database": "global",
"query": "select * from auth_groups_identity_provider_groups"
}
+----+---------------+----------------------------+
| id | auth_group_id | identity_provider_group_id |
+----+---------------+----------------------------+
| 1 | 1 | 1 |
+----+---------------+----------------------------+
Seems like an insert into the auth_groups_identity_provider_groups is causing issues?
I suggest to use 403 over 404 when users have no permission.
Consider the scenario:
Alice has no access to secret-project on the server
In the current state, lxd responds with
- 403 on
1.0/instances?project=nonexisting-project, but also with a - 403 on
1.0/instances?project=secret-project
It should definitely respond with 404 to 1.0/instances?project=nonexisting-project, because that project doesn't exist.
We shouldn't expose the existence of secret-project to Alice, hence we should always use 404 when users have no permission.
@markylaing I was playing around with different permissions and found a potential issue. I created a group with a single permission can_view_instances on project. Then I allocated this group to an oidc identity. Upon login, I can't view any instances and looking at the server debug logs, I see the below info:
DEBUG [2024-03-04T10:40:41Z] Error Response
{
"type": "error",
"status": "",
"status_code": 0,
"operation": "",
"error_code": 403,
"error": "User does not have entitlement \"can_view\" on object \"project:/1.0/projects/default\"",
"metadata": null
} http_code=403
Is this intended behaviour? Furthermore, I then changed the group permission to have can_view entitlement on project, the 403 response went away but no instances were returned from the server, seems like it was filtered out somehow.
@markylaing I was playing around with different permissions and found a potential issue. I created a group with a single permission
can_view_instancesonproject. Then I allocated this group to an oidc identity. Upon login, I can't view any instances and looking at the server debug logs, I see the below info:DEBUG [2024-03-04T10:40:41Z] Error Response { "type": "error", "status": "", "status_code": 0, "operation": "", "error_code": 403, "error": "User does not have entitlement \"can_view\" on object \"project:/1.0/projects/default\"", "metadata": null } http_code=403Is this intended behaviour? Furthermore, I then changed the group permission to have
can_viewentitlement onproject, the 403 response went away but no instances were returned from the server, seems like it was filtered out somehow.
That sounds like a bug to me. Will investigate when I get back to this after #12992. Thanks!
I suggest to use 403 over 404 when users have no permission.
Consider the scenario:
Alice has no access to
secret-projecton the server In the current state, lxd responds with
- 403 on
1.0/instances?project=nonexisting-project, but also with a- 403 on
1.0/instances?project=secret-projectIt should definitely respond with 404 to
1.0/instances?project=nonexisting-project, because that project doesn't exist.We shouldn't expose the existence of
secret-projectto Alice, hence we should always use 404 when users have no permission.
Just had a thought about this. If using 404 over 403 we'll need to think carefully about any endpoints used for probing permissions that will be used for the UI e.g. whether a user has permission to edit or delete an instance.
@markylaing I was playing around with different permissions and found a potential issue. I created a group with a single permission
can_view_instancesonproject. Then I allocated this group to an oidc identity. Upon login, I can't view any instances and looking at the server debug logs, I see the below info:DEBUG [2024-03-04T10:40:41Z] Error Response { "type": "error", "status": "", "status_code": 0, "operation": "", "error_code": 403, "error": "User does not have entitlement \"can_view\" on object \"project:/1.0/projects/default\"", "metadata": null } http_code=403Is this intended behaviour? Furthermore, I then changed the group permission to have
can_viewentitlement onproject, the 403 response went away but no instances were returned from the server, seems like it was filtered out somehow.
@mas-who Regarding this issue could you please try to reproduce with the latest build of this branch? After rebasing on #12992 I tried to reproduce but couldn't. Not sure if I'm misunderstanding something or if I've inadvertently fixed it :shrug: Thanks
I suggest to use 403 over 404 when users have no permission.
Hi @edlerd @mas-who
@markylaing and I have been chatting about this and have tried to come up with some guiding principles we hope to apply to API endpoints consistently. These are:
- Resources shouldn't be discoverable if you don't have access to them - this means that the content and response code of an endpoint shouldn't be different between the resource(s) existing or not having access to them. However naturally one may be able to view a resource but not modify it.
- For endpoints that are entity specific (e.g.
/1.0/instances/c1) where access to the entity can be checked using the requested URL only then in order to avoid making entities discoverable they should return a 404 when they do not exist or if the user doesn't have permission to view the resource. However if the user has permission to view the entity, but the request is for modifying the entity then it would be appropriate for a 403 response code. - For endpoints that are not entity specific (e.g.
/1.0/instances) where access to the entities in the list cannot be checked using the requested URL only, then an empty list with a 200 should be returned if the project doesn't exist or the user doesn't have view access to any resources within that project. The key thing to understand here is that even if the user doesn't have view access to the requested project, they may still have access to an instance within that project, and so we cannot deny access to the entire list endpoint based on the request project alone. As this would then allow discovering if the project exists if one does not have access to it.
Does that make sense? @markylaing is that achievable (thinking specifically point 2)?
I suggest to use 403 over 404 when users have no permission.
Hi @edlerd @mas-who
@markylaing and I have been chatting about this and have tried to come up with some guiding principles we hope to apply to API endpoints consistently. These are:
- Resources shouldn't be discoverable if you don't have access to them - this means that the content and response code of an endpoint shouldn't be different between the resource(s) existing or not having access to them. However naturally one may be able to view a resource but not modify it.
- For endpoints that are entity specific (e.g.
/1.0/instances/c1) where access to the entity can be checked using the requested URL only then in order to avoid making entities discoverable they should return a 404 when they do not exist or if the user doesn't have permission to view the resource. However if the user has permission to view the entity, but the request is for modifying the entity then it would be appropriate for a 403 response code.- For endpoints that are not entity specific (e.g.
/1.0/instances) where access to the entities in the list cannot be checked using the requested URL only, then an empty list with a 200 should be returned if the project doesn't exist or the user doesn't have view access to any resources within that project. The key thing to understand here is that even if the user doesn't have view access to the requested project, they may still have access to an instance within that project, and so we cannot deny access to the entire list endpoint based on the request project alone. As this would then allow discovering if the project exists if one does not have access to it.Does that make sense? @markylaing is that achievable (thinking specifically point 2)?
I think this is achievable. The gist will be that when performing an OpenFGA check request, we'll check the HTTP method. For GET we'll always return 404 if not accessible. For any other code we'll perform a check first with can_view and return 404 on fail, otherwise we'll check the requested entitlement (can_edit or can_delete). I'll need to validate this as I'm not sure it will work in all cases.
@markylaing I was playing around with different permissions and found a potential issue. I created a group with a single permission
can_view_instancesonproject. Then I allocated this group to an oidc identity. Upon login, I can't view any instances and looking at the server debug logs, I see the below info:DEBUG [2024-03-04T10:40:41Z] Error Response { "type": "error", "status": "", "status_code": 0, "operation": "", "error_code": 403, "error": "User does not have entitlement \"can_view\" on object \"project:/1.0/projects/default\"", "metadata": null } http_code=403Is this intended behaviour? Furthermore, I then changed the group permission to have
can_viewentitlement onproject, the 403 response went away but no instances were returned from the server, seems like it was filtered out somehow.That sounds like a bug to me. Will investigate when I get back to this after #12992. Thanks!
We have validated that this isn't a bug with the PR but is because the UI is requesting to view the project before it attempts to list instances. I would suggest that in the UI we attempt to list projects to get the drop down menu, but also have a mode where no project is set. You can still list instances using all-projects and users will be able to view the instances they have access to.
I think this is achievable. The gist will be that when performing an OpenFGA check request, we'll check the HTTP method. For GET we'll always return 404 if not accessible. For any other code we'll perform a check first with
can_viewand return 404 on fail, otherwise we'll check the requested entitlement (can_editorcan_delete). I'll need to validate this as I'm not sure it will work in all cases.
Thanks sounds good
@markylaing as discussed, I will just leave this comment here regarding idp groups for future reference. So it was found that after an OIDC identity logs in, if its idp groups were successfully mapped via the custom claim, the identity gets assigned to the correct lxd groups and therefore gets the right permissions. However, when we query the API for group memberships, the association between the lxd groups and the identity is missing. It was mentioned for idp mapped groups, the relationship between those groups and the identity is not currently stored in the database, so we can't get that data.
@mas-who and I have discussed this. IDP group mappings are contextual and are on a per-request basis. When listing identities, the IDP groups of the identity are not shown, and their membership in LXD groups is also not shown (again, because this information is not stored). This may be quite confusing and lead to a bad user experience. I think there are two options:
- Store the IDP groups as metadata in the identities table. We can return this in the API response of an identity so that the administrator can see what the IDP groups are on their last login. It is very important that the UI communicates clearly to the user that this information may not be accurate. LXD isn't in control of this information.
- Communicate very clearly via warning message that if a user is not a member of any groups, they may still have access to LXD via IDP group mappings. We can check if there are any IDP mappings by checking if
oidc.groups.claimis set, and listing the mappings, if the user does not have permission to view server settings or no IDP groups are found, the warning does not need to be displayed. If there are mappings are configured andoidc.groups.claimis set, display a warning to indicate that the admin should configure their permissions in their IDP.
I am personally in favour of 2. The user experience is not great in either case and I'd prefer that LXD doesn't store or present information that may be incorrect.
@markylaing as discussed, I will just leave this comment here regarding idp groups for future reference. So it was found that after an OIDC identity logs in, if its idp groups were successfully mapped via the custom claim, the identity gets assigned to the correct lxd groups and therefore gets the right permissions. However, when we query the API for group memberships, the association between the lxd groups and the identity is missing. It was mentioned for idp mapped groups, the relationship between those groups and the identity is not currently stored in the database, so we can't get that data.
@mas-who and I have discussed this. IDP group mappings are contextual and are on a per-request basis. When listing identities, the IDP groups of the identity are not shown, and their membership in LXD groups is also not shown (again, because this information is not stored). This may be quite confusing and lead to a bad user experience. I think there are two options:
1. Store the IDP groups as metadata in the identities table. We can return this in the API response of an identity so that the administrator can see what the IDP groups are **on their last login**. It is very important that the UI communicates clearly to the user that this information may not be accurate. LXD isn't in control of this information. 2. Communicate very clearly via warning message that if a user is not a member of any groups, they may still have access to LXD via IDP group mappings. We can check if there are any IDP mappings by checking if `oidc.groups.claim` is set, and listing the mappings, if the user does not have permission to view server settings or no IDP groups are found, the warning does not need to be displayed. If there are mappings are configured and `oidc.groups.claim` is set, display a warning to indicate that the admin should configure their permissions in their IDP.I am personally in favour of 2. The user experience is not great in either case and I'd prefer that LXD doesn't store or present information that may be incorrect.
Can we get LXD to return the list of current effective LXD groups when getting user info?
Can we get LXD to return the list of current effective LXD groups when getting user info?
Yes if we store the IdP groups in the identity metadata but the information may not be accurate if the IdP group membership has changed since the user last authenticated with LXD.
Edit: Additionally, since the metadata is not related to our IdP mappings via foreign key the information will not be accurate if an administrator renames or deletes a mapping. We can ignore this and return a "best effort".
@markylaing as discussed, I will just leave this comment here regarding idp groups for future reference. So it was found that after an OIDC identity logs in, if its idp groups were successfully mapped via the custom claim, the identity gets assigned to the correct lxd groups and therefore gets the right permissions. However, when we query the API for group memberships, the association between the lxd groups and the identity is missing. It was mentioned for idp mapped groups, the relationship between those groups and the identity is not currently stored in the database, so we can't get that data.
@mas-who and I have discussed this. IDP group mappings are contextual and are on a per-request basis. When listing identities, the IDP groups of the identity are not shown, and their membership in LXD groups is also not shown (again, because this information is not stored). This may be quite confusing and lead to a bad user experience. I think there are two options:
- Store the IDP groups as metadata in the identities table. We can return this in the API response of an identity so that the administrator can see what the IDP groups are on their last login. It is very important that the UI communicates clearly to the user that this information may not be accurate. LXD isn't in control of this information.
- Communicate very clearly via warning message that if a user is not a member of any groups, they may still have access to LXD via IDP group mappings. We can check if there are any IDP mappings by checking if
oidc.groups.claimis set, and listing the mappings, if the user does not have permission to view server settings or no IDP groups are found, the warning does not need to be displayed. If there are mappings are configured andoidc.groups.claimis set, display a warning to indicate that the admin should configure their permissions in their IDP.I am personally in favour of 2. The user experience is not great in either case and I'd prefer that LXD doesn't store or present information that may be incorrect.
@mas-who @edlerd I've discussed this with Tom and we have come up with the following approach:
- LXD will not store IdP groups in it's database or cache.
- The identities API will have the following changes:
GET /1.0/auth/identities?recursion=2will be dropped.GET /1.0/auth/identities/{authenticationMethod}?recursion=2will be dropped.GET /1.0/auth/identities?recursion=1will return the LXD groups that the identities are members of (this previously required recursion=2). They will not contain any effective groups that are calculated from the IdP groups claim.GET /1.0/auth/identities/{authenticationMethod}?recursion=1same as 3. above.GET /1.0/auth/identities/{authenticationMethod}/{nameOrIdentifier}- no change.- A new endpoint
GET /1.0/auth/identities/currentwill be added. This endpoint will return information about the identity that called the endpoint. It will return the same fields as 5. and two extra fields:effective_groups: A list of of LXD group names. These are all the groups that the identity is a member of either directly or indirectly (via IdP mapping).effective_permissions: A list of LXD permissions (same format asGET /1.0/auth/permissions). These are all the permissions that the user has via direct or indirect group membership.
- The groups API will have the following changes:
GET /1.0/auth/groups?recursion=1. Theidentitiesfield will now be a map of authentication method to list of identifiers.GET /1.0/auth/groups/{groupName}. Theidentitiesfield will now be a map of authentication method to list of identifiers.
Note that we cannot display "effective" fields for any user except for the one that is currently logged in and making the request.
A new endpoint
GET /1.0/auth/identities/currentwill be added. This endpoint will return information about the identity that called the endpoint. It will return the same fields as 5. and two extra fields:
effective_groups: A list of of LXD group names. These are all the groups that the identity is a member of either directly or indirectly (via IdP mapping).effective_permissions: A list of LXD permissions (same format asGET /1.0/auth/permissions). These are all the permissions that the user has via direct or indirect group membership.
Had a discussion with @mas-who about this: Does the effective permission list include all resources on the server? So that for instance foo in project bar, I can see if the current user has the can_delete entitlement -- directly or inherited from some parent like project or server.
Had a discussion with @mas-who about this: Does the effective permission list include all resources on the server? So that for instance foo in project bar, I can see if the current user has the can_delete entitlement -- directly or inherited from some parent like project or server.
No. It will just contain the permissions as they are defined in the groups that the user is a member of, either directly or via IdP mapping. E.g.
{
"entitlement": "can_view_instances",
"entity_type": "project",
"url": "/1.0/projects/default"
}
No. It will just contain the permissions as they are defined in the groups that the user is a member of, either directly or via IdP mapping.
I see, it's a good first step. I think for the UI, we need a more detailed way of checking if the user has permissions on a given object. I.e. they are currently viewing an instance, and we need to know if they can edit and/or delete it. We can't get this info from the endpoints results, as we would have to re-evaluate the permission model, which seems like a complex thing to do -- ideally would be done by openFGA directly and exposed to the UI. But that can be added at a later point.
@markylaing as discussed, I will just leave this comment here regarding idp groups for future reference. So it was found that after an OIDC identity logs in, if its idp groups were successfully mapped via the custom claim, the identity gets assigned to the correct lxd groups and therefore gets the right permissions. However, when we query the API for group memberships, the association between the lxd groups and the identity is missing. It was mentioned for idp mapped groups, the relationship between those groups and the identity is not currently stored in the database, so we can't get that data.
@mas-who and I have discussed this. IDP group mappings are contextual and are on a per-request basis. When listing identities, the IDP groups of the identity are not shown, and their membership in LXD groups is also not shown (again, because this information is not stored). This may be quite confusing and lead to a bad user experience. I think there are two options:
- Store the IDP groups as metadata in the identities table. We can return this in the API response of an identity so that the administrator can see what the IDP groups are on their last login. It is very important that the UI communicates clearly to the user that this information may not be accurate. LXD isn't in control of this information.
- Communicate very clearly via warning message that if a user is not a member of any groups, they may still have access to LXD via IDP group mappings. We can check if there are any IDP mappings by checking if
oidc.groups.claimis set, and listing the mappings, if the user does not have permission to view server settings or no IDP groups are found, the warning does not need to be displayed. If there are mappings are configured andoidc.groups.claimis set, display a warning to indicate that the admin should configure their permissions in their IDP.I am personally in favour of 2. The user experience is not great in either case and I'd prefer that LXD doesn't store or present information that may be incorrect.
@mas-who @edlerd I've discussed this with Tom and we have come up with the following approach:
LXD will not store IdP groups in it's database or cache.
The identities API will have the following changes:
GET /1.0/auth/identities?recursion=2will be dropped.
GET /1.0/auth/identities/{authenticationMethod}?recursion=2will be dropped.
GET /1.0/auth/identities?recursion=1will return the LXD groups that the identities are members of (this previously required recursion=2). They will not contain any effective groups that are calculated from the IdP groups claim.
GET /1.0/auth/identities/{authenticationMethod}?recursion=1same as 3. above.
GET /1.0/auth/identities/{authenticationMethod}/{nameOrIdentifier}- no change.A new endpoint
GET /1.0/auth/identities/currentwill be added. This endpoint will return information about the identity that called the endpoint. It will return the same fields as 5. and two extra fields:
effective_groups: A list of of LXD group names. These are all the groups that the identity is a member of either directly or indirectly (via IdP mapping).effective_permissions: A list of LXD permissions (same format asGET /1.0/auth/permissions). These are all the permissions that the user has via direct or indirect group membership.The groups API will have the following changes:
GET /1.0/auth/groups?recursion=1. Theidentitiesfield will now be a map of authentication method to list of identifiers.GET /1.0/auth/groups/{groupName}. Theidentitiesfield will now be a map of authentication method to list of identifiers.Note that we cannot display "effective" fields for any user except for the one that is currently logged in and making the request.
@markylaing regarding the effective_groups field, can I confirm that it's still a best effort estimation for the indirect groups? So we would still need to provide a sensible message in the UI to inform the user. Furthermore, would the groups returned in effective_groups include the identity_provider_groups field and what would happen if a lxd group is both allocated to the identity as well as mapped to the identity via idp groups?
So we would still need to provide a sensible message in the UI to inform the user. Furthermore, would the groups returned in
effective_groupsinclude theidentity_provider_groupsfield and what would happen if a lxd group is both allocated to the identity as well as mapped to the identity via idp groups?
This will be a unified list of all effective groups being applied to the user, whether explicitly assigned or implicitly assigned via idp group mappings.
I think for the UI, we need a more detailed way of checking if the user has permissions on a given object. I.e. they are currently viewing an instance, and we need to know if they can edit and/or delete it.
Yes that is what is being considered here https://github.com/canonical/lxd/issues/13000
@mas-who I see Tom has already clarified but I'll expand a bit:
@markylaing regarding the effective_groups field, can I confirm that it's still a best effort estimation for the indirect groups? So we would still need to provide a sensible message in the UI to inform the user.
No. This is accurate. It will contain all the permissions that apply to that particular user. We are able to do this for the user who makes the request because we have the IdP groups in the request context.
Furthermore, would the groups returned in effective_groups include the identity_provider_groups field and what would happen if a lxd group is both allocated to the identity as well as mapped to the identity via idp groups?
Here is some example output with annotations:
groups:
- my-group # Direct LXD group membership.
authentication_method: oidc
type: OIDC client
id: [email protected]
name: [email protected]
effective_groups:
- my-group # Direct and possible indirect group membership.
- group2 # Definite indirect group membership since it's not in the list above.
effective_permissions: # Permissions may result from "my-group" or "group2" or any combination.
- entity_type: server
url: /1.0
entitlement: admin
- entity_type: project
url: /1.0/projects/default
entitlement: can_view_instances