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

proxy: Assign user roles from OIDC claim #5784

Merged
merged 9 commits into from
Mar 20, 2023
Merged

Conversation

rhafer
Copy link
Contributor

@rhafer rhafer commented Mar 9, 2023

Description

This adjusts the account resolver middleware to update a user's role assignment from a claim provided via the IDPs userinfo endpoint.

It's still work in progress and needs some adjustments before we can merge it:

  • Make the role claim name configurable. Currently it's hardcoded to roles
  • Make the role mapping (claim value to ocis role name) configurable. Currently the mapping is hardcoded to the roles deployed in the ocis_keycloak deployment example.
  • Allow to turn off the default role assignment that's currently happening in the graph API, which is somewhat annoying especially when AutoProvisioning is enabled (graph: Allow to disable the default role assignment on user creation #5828).
  • Turn off creation for default role assigment for admin and demo users in settings service (User assignments-list gets longer after every restart on default users  #3432 )
  • Turn off creation of the admin user in idm, for this kind of setup (Allow ADMIN_USER_ID being empty #5842)
  • Add some caching to avoid running ListRoles with every request
  • Restructure the code a bit to make UpdateRoleAssignmentsFromClaims() somewhat readable
  • Update Readme
  • Adapt keycloak deployment to skip admin user creating, and use oidc role assignment
  • For later probably: Try to be a bit smarter about how often to check the role assignments. Currently this happens with every role request. Might make sense to only do that after receiving a new access_token (how?), or when the userinfo c
    cache expired.

For testing purposes this can be used with the ocis_keycloak deployment, which already has some roles assigned to the demo users.

As ocis only allows one role per user. The code errors out if more than one role mapping is found for a user. We might need to change that behaviour somehow. See also: #5750 (review)

Currently this uses a very hacky way for obtaining a reva token with admin privileges (need for actually assigning the roles). We really need service accounts (#5550) for stuff like this.

Closes: #5669

@update-docs
Copy link

update-docs bot commented Mar 9, 2023

Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a changelog item based on your changes.

@rhafer
Copy link
Contributor Author

rhafer commented Mar 9, 2023

@wkloucek @jfd Feel free to try this out.

@wkloucek
Copy link
Contributor

I configured Einstein to be an "ocisAdmin" in Keycloak before his first login. Therefore, his access token looks like this:

{
  "exp": 1678432508,
  "iat": 1678432208,
  "auth_time": 1678432177,
  "jti": "dcab3320-383e-4410-95c0-50da87746588",
  "iss": "https://keycloak.owncloud.test/realms/oCIS",
  "aud": "account",
  "sub": "0a9f434c-4864-49cf-ac15-46ed0f49d59b",
  "typ": "Bearer",
  "azp": "web",
  "session_state": "ffbe2499-7803-43d0-b2ab-61aed444896d",
  "allowed-origins": [
    "https://ocis.owncloud.test"
  ],
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid email profile",
  "sid": "ffbe2499-7803-43d0-b2ab-61aed444896d",
  "email_verified": true,
  "roles": [
    "offline_access",
    "uma_authorization",
    "ocisAdmin"
  ],
  "name": "Albert Einstein",
  "preferred_username": "einstein",
  "given_name": "Albert",
  "family_name": "Einstein",
  "email": "einstein@example.org"
}

But oCIS says:

{"level":"error","service":"proxy","error":"too many roles assigned","time":"2023-03-10T07:10:10.330947981Z","line":"github.com/owncloud/ocis/v2/services/proxy/pkg/middleware/account_resolver.go:103","message":"Could not get user roles"}

Another usecase was that I added a fresh user with the "ocisAdmin" role. The user could log in and do admin stuff. But when you change the role to "ocisSpaceAdmin" or "ocisUser", this user won't even see his personal space (in the graph api) anymore!?

@rhafer
Copy link
Contributor Author

rhafer commented Mar 10, 2023

But oCIS says:

{"level":"error","service":"proxy","error":"too many roles assigned","time":"2023-03-10T07:10:10.330947981Z","line":"github.com/owncloud/ocis/v2/services/proxy/pkg/middleware/account_resolver.go:103","message":"Could not get user roles"}

Did you by chance restart ocis multiple times? It yes, this might be caused by #3432 (the default role assignment are created with every restart of ocis).

Which reminds we that we need to disable the default role assignment and the creation of the admin user in the idm in this kind of setup. (I added both to checklist in the description)

Another usecase was that I added a fresh user with the "ocisAdmin" role. The user could log in and do admin stuff. But when you change the role to "ocisSpaceAdmin" or "ocisUser", this user won't even see his personal space (in the graph api) anymore!?

That seem to be a bug. Though changing roles worked fine for me when briefly testing it. Need to take a closer look.

@wkloucek
Copy link
Contributor

wkloucek commented Mar 10, 2023

But oCIS says:

{"level":"error","service":"proxy","error":"too many roles assigned","time":"2023-03-10T07:10:10.330947981Z","line":"github.com/owncloud/ocis/v2/services/proxy/pkg/middleware/account_resolver.go:103","message":"Could not get user roles"}

Did you by chance restart ocis multiple times? It yes, this might be caused by #3432 (the default role assignment are created with every restart of ocis).

Could be the case that I reused an already existing docker volume 🤔

Which reminds we that we need to disable the default role assignment and the creation of the admin user in the idm in this kind of setup. (I added both to checklist in the description)

That would be kind of a "OIDC Provider has the authority about user roles"-flag? So no more "SETTINGS_ADMIN_USER_ID" and editable roles in the WebUI!?

Another usecase was that I added a fresh user with the "ocisAdmin" role. The user could log in and do admin stuff. But when you change the role to "ocisSpaceAdmin" or "ocisUser", this user won't even see his personal space (in the graph api) anymore!?

That seem to be a bug. Though changing roles worked fine for me when briefly testing it. Need to take a closer look.

@rhafer
Copy link
Contributor Author

rhafer commented Mar 10, 2023

That would be kind of a "OIDC Provider has the authority about user roles"-flag? So no more "SETTINGS_ADMIN_USER_ID" and editable roles in the WebUI!?

Yeah. I think so. If we get the roles from the IDP we should not allow overriding them locally. This will just cause confusion (and also pretty difficult synchronization and conflict issues). Do you disagree?

@tbsbdr I guess this is probably also interesting for you.

@kulmann This also means we need some capability to tell the WebUI that roles cannot be re-assigned.

@ownclouders
Copy link
Contributor

ownclouders commented Mar 15, 2023

💥 Acceptance test Core-API-Tests-ocis-storage-3 failed. Further test are cancelled...

@rhafer rhafer force-pushed the oidc-roles branch 9 times, most recently from e7c3ea1 to 40bb15f Compare March 16, 2023 16:27
@rhafer rhafer changed the title wip: assign user roles from OIDC claim assign user roles from OIDC claim Mar 16, 2023
@rhafer rhafer changed the title assign user roles from OIDC claim proxy: Assign user roles from OIDC claim Mar 16, 2023
@rhafer rhafer marked this pull request as ready for review March 16, 2023 16:46
@rhafer rhafer requested review from butonic and micbar and removed request for lookacat and kulmann March 16, 2023 16:46
@rhafer rhafer self-assigned this Mar 16, 2023
@rhafer
Copy link
Contributor Author

rhafer commented Mar 16, 2023

This should be ready for review now. Provided the CI is green.

Copy link
Collaborator

@kobergj kobergj left a comment

Choose a reason for hiding this comment

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

Looks good in general. Just nitpicking as always...

services/proxy/pkg/config/config.go Outdated Show resolved Hide resolved
services/proxy/pkg/config/config.go Outdated Show resolved Hide resolved
services/proxy/pkg/userroles/defaultrole.go Outdated Show resolved Hide resolved
return nil, err
case 1:
// exactly one mapping. This is right
break
Copy link
Collaborator

Choose a reason for hiding this comment

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

Curious: The break is needed as the linter won't allow having an empty branch on the switch? Or is there another reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm. I think that this was just my C habits breaking though. I am not even sure the linter would complain about this.

services/proxy/pkg/userroles/oidcroles.go Outdated Show resolved Hide resolved
services/proxy/pkg/userroles/oidcroles.go Outdated Show resolved Hide resolved
To align with what we're using everywhere else.
This removes the "withRoles" flag from the GetUserByClaims lookup and move the
functionality into a separate method. This should make the code a bit more readable
in preparation for maintaining the RoleAssignments from OIDC claims.
This will make it easier to add/remove options to the backend in the
future.
rhafer and others added 6 commits March 20, 2023 12:38
This moves the lookup and the creation of the users' role assignemt out
of the user backend into its own interface. This makes the user backend
a bit simpler and allows to provide different implemenation for the user
role assignment more easily.
Add a UserRoleAssigner implementation that extract role names from the
users' claims and creates role assignments in the settings service based
on a configured mapping of claim values to ocis role names.

Closes: owncloud#5669
Avoid torturing the settings service with "ListRoles" request for
every incoming request to the proxy.
The role Mapping is refreshed if cached data is older than 5 minutes.
Response bodies need to be closed
@sonarcloud
Copy link

sonarcloud bot commented Mar 20, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 2 Code Smells

3.0% 3.0% Coverage
0.0% 0.0% Duplication

@rhafer rhafer requested a review from kobergj March 20, 2023 11:48
Copy link
Collaborator

@kobergj kobergj left a comment

Choose a reason for hiding this comment

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

Awesome now 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ocis] Autoprovision user role Assignments from OIDC claims
6 participants