Harbor: Can not delete user login with oidc

Created on 26 Jul 2019  路  30Comments  路  Source: goharbor/harbor

I use dex as oidc provider. when delete a user from dex. user can not login harbor dashboard, but can still use docker command. I can't delete user in harbor dashboard

image

needtriage

Most helpful comment

I also echo the sentiment of https://github.com/goharbor/harbor/issues/8424#issuecomment-634683478 (@wmgroot) because we are not mapping users directly to a project; rather, we are using keycloak groups to handle this.

At t0, when a new user signs up, the user is requested to create an internal user within harbor; I don't know if this is necessary if the username (in this case a company email address) can be used from OIDC.

Anyway, if I were to go through and delete the user on the keycloak side (just for testing), harbor will not let the user log back in (I suppose because the UUID changed) even after authenticating with Harbor (our OIDC identity broker).

So, I ran into this scenario above while initially configuring all the OIDC groups and harbor projects to work properly.

In order to fix stale users, I had to run the following many times to delete non-existent users so that the real ones could log in via Keycloak. For my setup, keycloak is in an identity brokering mode so it does not directly manage any user credentials; it is handled by an IT managed authoritative Azure AD service.

Step 1: log into the database container

# Get the pod name
POD_NAME=`kubectl get pods -n harbor --output=json | jq -r -j '.items[].metadata | select(.name | startswith("database")) | .name'`

# Log into the pod
kubectl exec -it -n slr-system $POD_NAME -- bash

# Drop into the postgres sql cli
psql -U postgres

# Follow commands below.
# Examples:
#    username == Some.User
#    user_id  == 0

step 2: delete the user, throughout the db tables, via the user_id

\c registry

# Determine user_id
select user_id from harbor_user where username = 'Some.User';

# 
# Use user_id from previous step to delete the user across all the tables;
# e.g. replace owner_id = 0, user_id = 0, entity_id = 0 sections with the correct user_id
#
delete from project where owner_id = 0;
delete from oidc_user where user_id = 0;
delete FROM project_member where (entity_id = 0 AND entity_type = 'u');
delete from harbor_user where user_id = 0;

Anyway, the fact that I have to do the above is crazy as OIDC/LDAP allow this to be decoupled; I would rather give the authz configuration take precedence and let keycloak tell harbor what the user/group has access to. The guidance should be that a global identifier should be used for the user; in my case, an immutable global identifier is an employee's email address.

So, ideally, in each webui view we would check if the user is logged in via harbor local database, ldap, or if there is a JWT from OIDC (e.g. no local username is required AFAIK).

My recommendation would be that if there is a user defined in the local database, then clearly the harbor admin wants to use harbor managed users. However, if LDAP/OIDC is used, then the authoritative source should be those systems. If a user named "employee.[email protected]" is using harbor, and temporarily leaves the company, then comes back; then the resources of that "employee.[email protected]" should be accessible by them. Harbor does not need to manage if the user exists or not; just track the mappings by OIDC UUID or by email address.

All 30 comments

@annProg This is by design, currently in Harbor any non-local user can't be removed after on-boarded.

closing as wontfix

Hi, We encountered similar issue with Keycloak. After deleting the user inside keycloak and recreate one with the same name, the user will not be able to login to harbor with oidc anymore. We have to delete the user in harbor or it's locked out forever. I guess the only option is to drop the harbor user in db directly.

How is this a wontfix? We're having the same issue as @kkzxak47 , where we have a couple of test users that are now stuck there forever, and a person who entered his full name instead of his username. Both can't be deleted/renamed ( and i can't seem to find it in the postgres db so delete/rename manually). An option to delete the 'local' copy in Harbor would be much appreciated. Whenever the user logs in again through OIDC, a new user can be created.

Found a workaround which hopefully doesn't break anything else ;-) :

\c registry
delete from oidc_user where user_id = xx;
delete from harbor_user where user_id = xx;

This is a valid issue. Those running harbor with any auth method need the ability to remove the locally made users. wontfix does not feel like the appropriate conclusion to this issue. OIDC seems to have limited functionality all throughout harbor.

I agree with verwilst's complaints that there isn't a valid workflow to recreate or change attributes about users who are created via OIDC. I don't think manually modifying values in postgres is intended to be the canonical workflow to address these issues. I think the need for this feature is simple and valid, and should be revisited.

I experienced same situation.
I am using harbor with keycloak for oidc,
for test, I remove my id in keycloak and create again,
after then, I can not log in harbor and admin can not remove user id.
I think harbor can accept username already created,
and admin can remove user id, there's no problem.

Can this be re-opened?

we also experienced the same problem. What is happening is harbor is prompting the user to set a user name for first login when connecting to OIDC not with the actual username from username and they keep forgetting their username. When we go to harbor not able to delete it.

We have the exact same problem as @verwilst. A feature to delete onboarded users in the local DB would be very useful.

For compliance purposes, this could cause issues with auditors

same issue; can't delete user that is non-existent anymore.

I also had the issue, in my case I migrated our users to another issuer, their uuid changed but not the email/username. So I just needed to update the subiss column of the table oidc_user to retrieve my users. Luckily for me I only had 10 users to change...

1st run:
select h.user_id, o.subiss, h.email from harbor_user h inner join oidc_user o on o.user_id = h.user_id;

then for every user:
update oidc_user set subiss = 'the-new-user-uuidhttps://mynewissuer.com/auth/realms/myrealm' where user_id = 13;

Guys, the problem is there's disconnection between Harbor's DB and the ID provider. Allowing admin to remove a user, when that removal happens, the user may still exists in the ID provider. We need to consider the case after jack is removed from Harbor's DB, what if the user jack login via OIDC provider again?
Do we recover the removed jack from DB or create a new record?

As for the issue that users keep forgetting his username, or mis-typed it during onboard, this PR may mitigate it:https://github.com/goharbor/harbor/pull/9311

I don't think we can make decision to allow user to change his username right now, considering Harbor also use the same user table and workflow for LDAP users, we need to be very careful to avoid negative side effects.

Sorry for the late response.

If you still have some idea in terms of how we should improve this part, please open a new issue.

@reasonerjt why don't we just discuss on this ticket, I'm reopening to work this through.

The reason why this we don鈥檛 allow deleting non-local users is there is no way to tell the difference btw user being deleted on the OIDC side or they just entered the wrong credentials. That information doesn鈥檛 come through to us on the token, Dex is just fronting for the authn back-end even and it just handle connecting harbor with the back-end. So if we allow deleting on harbor, that would be problematic if it was actually someone else attempting to login. I think most of the users are wanting to delete a username that they mistyped but that will be mitigated by this PR where we don鈥檛 provide them with that option, the username is taken directly from the OIDC provider - https://github.com/goharbor/harbor/pull/9311

What if we create a UX workflow that allows user to confirm deleting in Harbor but they bear the responsibility of re-adding that user to all the projects and so on if they accidentally deleted the wrong user

What if we create a UX workflow that allows user to confirm deleting in Harbor but they bear the responsibility of re-adding that user to all the projects and so on if they accidentally deleted the wrong user

I was thinking about the same workflow when I wanted to delete my users.

IMHO, if someone is struggling with project permissions after deleting a user AND have OIDC enabled. This person would better need to configure and manage permissions using groups rather than recovering from a previous user profile.

I understand that user will be removed from all projects, and all of their permissions will be reset. That isn't a problem for me, because our project permissions are group-based, so nothing depends directly on the user.

If I'm already having to remove users from the database directly (potentially for compliance reasons after an employee leaves, as jonhatallasf mentions), why not simplify the process with a confirmation box that warns the user?

Guys, the problem is there's disconnection between Harbor's DB and the ID provider. Allowing admin to remove a user, when that removal happens, the user may still exists in the ID provider. We need to consider the case after jack is removed from Harbor's DB, what if the user jack login via OIDC provider again?

That's simple: the user is recreated. This request is about a feature for Harbor-Admins to clean up after testing, possibly after deleting the test user on the ID provider, or to re-test the onboarding workflow without creating a new user on the ID provider.

It is not about a way for users to change their username.

It feels like a rather arbitrary limitation to not allow admins remove users in Harbors database only because they have been provisioned through OIDC.

@rhuitl

The decision was if a user was onboarded to Harbor via external IDP such as OIDC / LDAP, he can't be removed from Harbor's DB, instead, he should be removed from external IDP so he can no longer log in to Harbor.

When the user is recreated, will he have the membership he previously had? It is not simple to make things consistent across all external IDP. If we make the behavior different from OIDC onboarded user to LDAP onboarded user, things can also get confusing, and the workflow is hard to maintain, we want to avoid that.

That's why I suggest we think it through before make any quick fix or decision.

AFAIK, when you have OIDC users, you have two ways of handling permissions:

  1. Map a claim to groups
  2. Manually add users to projects

I don't know if you store the group membership in the Harbor database. It doesn't seem to be necessary as the token will contain the claims and it's not really needed to duplicate this information. When membership changes on the IP side, the next time the user logs in (*), Harbor will see the updated group membership.

Actually you wouldn't even have to store an OIDC user in your database, even though it has the advantage of enabling (2) and allows picking a different username for Harbor.

I understand that with LDAP, the situation is different, because you can pull a list of users and that will reflect users deleted on the LDAP side. However, again AFAIK, I don't think there is a way to do this with OIDC (please correct me if I'm wrong!) - when a user is deleted on the OIDC IP, there is no way for the OIDC client to learn about this.

Therefore, I think you may not be able to keep the LDAP and OIDC flows exactly the same.

*) When changing claims on the ID side (in my case Keycloak), a user has to log into Harbor again before the new claims take effect. I did not investigate this too much, my current recommendation for our users is to log into Harbor again using an incognito browser window. This updates the group membership and even the non-incognito session picks up the new permissions.

I also echo the sentiment of https://github.com/goharbor/harbor/issues/8424#issuecomment-634683478 (@wmgroot) because we are not mapping users directly to a project; rather, we are using keycloak groups to handle this.

At t0, when a new user signs up, the user is requested to create an internal user within harbor; I don't know if this is necessary if the username (in this case a company email address) can be used from OIDC.

Anyway, if I were to go through and delete the user on the keycloak side (just for testing), harbor will not let the user log back in (I suppose because the UUID changed) even after authenticating with Harbor (our OIDC identity broker).

So, I ran into this scenario above while initially configuring all the OIDC groups and harbor projects to work properly.

In order to fix stale users, I had to run the following many times to delete non-existent users so that the real ones could log in via Keycloak. For my setup, keycloak is in an identity brokering mode so it does not directly manage any user credentials; it is handled by an IT managed authoritative Azure AD service.

Step 1: log into the database container

# Get the pod name
POD_NAME=`kubectl get pods -n harbor --output=json | jq -r -j '.items[].metadata | select(.name | startswith("database")) | .name'`

# Log into the pod
kubectl exec -it -n slr-system $POD_NAME -- bash

# Drop into the postgres sql cli
psql -U postgres

# Follow commands below.
# Examples:
#    username == Some.User
#    user_id  == 0

step 2: delete the user, throughout the db tables, via the user_id

\c registry

# Determine user_id
select user_id from harbor_user where username = 'Some.User';

# 
# Use user_id from previous step to delete the user across all the tables;
# e.g. replace owner_id = 0, user_id = 0, entity_id = 0 sections with the correct user_id
#
delete from project where owner_id = 0;
delete from oidc_user where user_id = 0;
delete FROM project_member where (entity_id = 0 AND entity_type = 'u');
delete from harbor_user where user_id = 0;

Anyway, the fact that I have to do the above is crazy as OIDC/LDAP allow this to be decoupled; I would rather give the authz configuration take precedence and let keycloak tell harbor what the user/group has access to. The guidance should be that a global identifier should be used for the user; in my case, an immutable global identifier is an employee's email address.

So, ideally, in each webui view we would check if the user is logged in via harbor local database, ldap, or if there is a JWT from OIDC (e.g. no local username is required AFAIK).

My recommendation would be that if there is a user defined in the local database, then clearly the harbor admin wants to use harbor managed users. However, if LDAP/OIDC is used, then the authoritative source should be those systems. If a user named "employee.[email protected]" is using harbor, and temporarily leaves the company, then comes back; then the resources of that "employee.[email protected]" should be accessible by them. Harbor does not need to manage if the user exists or not; just track the mappings by OIDC UUID or by email address.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I'd like to reiterate @n0rig, this issue is still a concern for us as we're working toward rolling out Harbor into production use, we have quite large organization and we need the ability to remove stale accounts as well as fix/handle any issues that may arise during onboarding or rejoining of an employee.

I think there's also an issue here with project's ownership, if an IDP authenticated user created a project and is no longer enrolled into the IDP, Admins should have a way to transfer his project(s) ownership to another user, AFAICT this can only be done today by raw DB updates.

@dkulchinsky I don't think you are talking about the same scenario as @n0rig
As for ownership, a project owner is the user who created the project, when a owner leaves admin can assign another project admin, so I don't think we need to transfer to ownership. In other words, you may think of owner as creator of a project.

@n0rig

At t0, when a new user signs up, the user is requested to create an internal user within harbor; I don't know if this is necessary if the username (in this case a company email address) can be used from OIDC.

If my understanding is correct, it's some internal process within your company, and I don' think it's necessary if you use OIDC auth mode.

Anyway, if I were to go through and delete the user on the keycloak side (just for testing), harbor will not let the user log back in (I suppose because the UUID changed) even after authenticating with Harbor (our OIDC identity broker).

If you remove a user from keycloak and add it back, it's correct to treat it as a different user. If it's for testing purpose you should use testing user.

@reasonerjt thanks for your comment, can you share how can I transfer a project "creator" role to another user?

with regard to the other concerns, I think they are still valid, it's fairly common for users to leave and later join back the company, at which point they get the same username in idp but with different sub claim, so they won't be able to get onboarded (we tested this scenario).

This issue is 1+ year old, so for what its worth, this is my current use case.

When a developer has left the company
I want to offboard developers from Harbor (in addition to offboarding them in Github)
So that my Harbor users list reflects the reality of who has access to the system

Given an employee has left a developer team
When I remove him from the relevant Github group
And I remove him from the relevant Harbor group
Then I don't see his name anymore in Harbor

What is the point of having delete user option when it is not usable? Either fix it or remove it... It just confuses the people. IMO this should be added.

Was this page helpful?
0 / 5 - 0 ratings