diff --git a/.docker/dist.tar.gz b/.docker/dist.tar.gz index 8de17c93ea61448bb57c66d16d836b7340fa000b..13e91ed189c2425dbb2d2493cc6fd4fa9d949b3e 100644 Binary files a/.docker/dist.tar.gz and b/.docker/dist.tar.gz differ diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 27d53063c3911c71379833810e0ecf905a38285a..d13e63c803d544ef129a6f03dbf6267ab6c2f0ec 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -346,7 +346,6 @@ services: OPENSEARCH_PORT: ${OPENSEARCH_PORT:-9200} OPENSEARCH_USERNAME: ${SEARCH_DB_USERNAME:-admin} OPENSEARCH_PASSWORD: ${SEARCH_DB_PASSWORD:-admin} - LOG_LEVEL: ${LOG_LEVEL:-info} depends_on: dbrepo-search-db: condition: service_healthy diff --git a/.docs/api/auth-service.md b/.docs/api/auth-service.md index f6c32497c79727a5b4db8afaea51138e1ea2867f..40ad6d8fd54825245574e578bff4c9fd7de1b463 100644 --- a/.docs/api/auth-service.md +++ b/.docs/api/auth-service.md @@ -19,10 +19,37 @@ of immutable properties (id, username) is mirrored in the [Metadata Database](.. ## Identities -:octicons-tag-16:{ title="Minimum version" } 1.4.4 - -Identities can also be added in Keycloak directly. When requesting a JWT token from the `/api/user` endpoint, the -immutable properties mentioned in c.f. [Overview](#overview) are copied transparent to the user on first login. +:octicons-tag-16:{ title="Minimum version" } 1.4.5 + +Identities are managed via LDAP through the [Identity Service](../identity-service). The normal workflow is that the +[Metadata Service](../metadata-service) adds identities when user register. In some cases, where this is not possible +(e.g. in workshop-scenarios where accounts are created before the workshop starts), identities need to be created +manually in Keycloak. The recommended workflow is: + +1. Login to the Auth Service as **Admin** and in the dbrepo realm navigate to **Users** +2. Click the **Add user** button and fill out the Username field and assign the group `researchers` by clicking + the **Join Groups** and selecting it. Click **Join** and **Create**. +3. Click the **Credentials** tab above and **Set password**. In the popup window assign a secure password to the user + and set **Temporary** to `Off`. + + !!! example "Create user with specific id" + + The user id is created automatically. In case you need to create a user with specific id such as in migration + scenarios, you need to change the `entryUUID` in the [Identity Service](../identity-service) by modifying this + protected attribute in `relax` mode: + + ```bash + echo "dn: uid=<username>,ou=users,dc=dbrepo,dc=at + changetype: modify + replace: entryUUID + entryUUID: 506ae590-11a2-4d2d-82b8-45121c6b4dab" | \ + ldapmodify -h localhost -p 1389 -D cn=admin,dc=dbrepo,dc=at -c -x -e relax \ + -w<adminpassword> + ``` + +4. Finally you need to query the user info once by navigating again to **Users** + and search for the **Username** and click :arrow_right: to search. Click the username and ensure that the + **User metadata** contains the entry **LDAP_ID**. ## Groups diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java index 173b3ef95df3f8c233cbc629f9769c0a694aebe9..4be54d5edd1ed39168b97a00177d87d09a7a87ee 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java @@ -372,11 +372,11 @@ public class UserEndpoint { log.error("Failed to modify user password: not current user"); throw new NotAllowedException("Failed to modify user password: not current user"); } - userService.updatePassword(user, data); authenticationService.updatePassword(user, data); for (Database database : databaseService.findAllAccess(userId)) { databaseService.updatePassword(database, user); } + userService.updatePassword(user, data); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java index 3c2ef1340ef8381a46c7277213d72311b5b357d6..bb3bcbb094ad1e9a2510abe20b9649ee73e6e975 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java @@ -191,7 +191,8 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void updateUserCredentials_succeeds() throws AuthServiceException, AuthServiceConnectionException { + public void updateUserCredentials_succeeds() throws AuthServiceException, AuthServiceConnectionException, + UserNotFoundException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java index 5a4690892f890097f636a868ab9d69aadb0c6ef2..5becb9225a42db3ab451dc054663e811e7c71629 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java @@ -109,7 +109,7 @@ public class UserServiceUnitTest extends AbstractUnitTest { @Test public void updatePassword_succeeds() throws AuthServiceException, AuthServiceConnectionException, - CredentialsInvalidException { + UserNotFoundException { /* mock */ doNothing() diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java index 71e30fb8606afc9c1fcef0c6fea3518bd7143d60..94ea986f78727a6fdc927b4e7ebb25ca6f0616bd 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -40,7 +40,7 @@ public interface KeycloakGateway { * @param password The user credential. */ void updateUserCredentials(UUID id, UserPasswordDto password) throws AuthServiceException, - AuthServiceConnectionException; + AuthServiceConnectionException, UserNotFoundException; /** * Finds a user in the metadata database by given username. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 38045e0399f00e0f4427a26aa85b4fe1274eeaa1..bce9d6e264b5283864c4e0ce4d2a157bd3d7dab4 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -161,7 +161,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { @Override public void updateUserCredentials(UUID id, UserPasswordDto data) throws AuthServiceException, - AuthServiceConnectionException { + AuthServiceConnectionException, UserNotFoundException { final UpdateCredentialsDto payload = metadataMapper.passwordToUpdateCredentialsDto(data.getPassword()); final String path = "/admin/realms/dbrepo/users/" + id; log.trace("update user credentials at endpoint {} with path {}", keycloakConfig.getKeycloakEndpoint(), path); @@ -171,6 +171,9 @@ public class KeycloakGatewayImpl implements KeycloakGateway { } catch (HttpServerErrorException e) { log.error("Failed to update user credentials: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); + } catch (HttpClientErrorException.NotFound e) { + log.error("Failed to update user credentials: user not found: {}", e.getMessage()); + throw new UserNotFoundException("User not found", e); } catch (Exception e) { log.error("Failed to update user: unexpected response: {}", e.getMessage()); throw new AuthServiceException("Unexpected result", e); diff --git a/docker-compose.yml b/docker-compose.yml index c2927c1c651ad8244426595f074a4813884b3cc1..3c78d4d9e9db11765aa5ea47b7f4c781c9ca1743 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -403,7 +403,6 @@ services: OPENSEARCH_PORT: ${OPENSEARCH_PORT:-9200} OPENSEARCH_USERNAME: ${SEARCH_DB_USERNAME:-admin} OPENSEARCH_PASSWORD: ${SEARCH_DB_PASSWORD:-admin} - LOG_LEVEL: ${LOG_LEVEL:-info} depends_on: dbrepo-search-db: condition: service_healthy diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index f96cf27b47bb0492479bd7ae45e2389870c8f9ef..2b18ed14222517593b1d9a31ec3bf67633fd2e91 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -306,7 +306,7 @@ brokerservice: ## @param brokerservice.ldap.uidField The field containing the user id. uidField: uid ## @param brokerservice.ldap.basedn The base domain name containing the users. - basedn: ou=users,dc=dbrepo,dc=at + basedn: dc=dbrepo,dc=at ## @param brokerservice.ldap.userDnPattern The pattern to determine the user. userDnPattern: ${username} auth: