diff --git a/ozgcloud-elasticsearch-operator/pom.xml b/ozgcloud-elasticsearch-operator/pom.xml index 76525653137c79b8db0d17b3c7c7284e6bff3cc3..23c8410368f60e39095575a515af48a6d2f325cf 100644 --- a/ozgcloud-elasticsearch-operator/pom.xml +++ b/ozgcloud-elasticsearch-operator/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>de.ozgcloud</groupId> <artifactId>ozgcloud-operator-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java index 24899d8fd8ce95377de40d38e4d0c676b7e1226b..de9fa2f206e9b9f6d100297df12d17ec9ba58be4 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/ElasticsearchReconciler.java @@ -50,7 +50,7 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch try { return new String(Base64.getDecoder().decode(encodedPassword)); } catch (Exception e) { - throw new RuntimeException("Could not decode password from secret."); + throw new RuntimeException("Could not decode password from secret.", e); } } diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java index 3d6a0c8f2144b33a5210685c699d85765ffbf879..3a915338a69f421ca3ab42fd6dcd088458c39f3d 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/OzgCloudElasticsearchService.java @@ -54,10 +54,7 @@ public class OzgCloudElasticsearchService { } public void createIndexIfMissing(String name) throws Exception { - LOG.debug("{}: Check elasticsearch index...", name); - if (!remoteService.existsIndex(name)) { - remoteService.createIndex(name); - } + remoteService.createOrUpdateIndex(name); } public void createSecurityRoleIfMissing(String roleName) throws Exception { @@ -81,24 +78,15 @@ public class OzgCloudElasticsearchService { } public void deleteSecurityUserIfExists(String userName) throws Exception { - LOG.debug("{}: Check delete elasticsearch user...", userName); - if (remoteService.existsSecurityUser(userName)) { - remoteService.deleteSecurityUser(userName); - } + remoteService.deleteSecurityUser(userName); } public void deleteSecurityRoleIfExists(String roleName) throws Exception { - LOG.debug("{}: Check delete elasticsearch role...", roleName); - if (remoteService.existsSecurityRole(roleName)) { - remoteService.deleteSecurityRole(roleName); - } + remoteService.deleteSecurityRole(roleName); } public void deleteIndexIfExists(String indexName) throws Exception { - LOG.debug("{}: Check delete elasticsearch index ...", indexName); - if (remoteService.existsIndex(indexName)) { - remoteService.deleteIndex(indexName); - } + remoteService.deleteIndex(indexName); } public void createCertificateIfMissing(String namespace) { @@ -111,7 +99,7 @@ public class OzgCloudElasticsearchService { createCredentialSecret(namespace, secretResource); } } catch (Exception e) { - throw new RuntimeException("Certificate secret creation failed " + namespace); + throw new RuntimeException("Certificate secret creation failed " + namespace, e); } } diff --git a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java index 958c9f03801f39306a94a4e4097067dede362cce..e401f95bcdbb683d3ebaf193d5280bb923d105d9 100644 --- a/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java +++ b/ozgcloud-elasticsearch-operator/src/main/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteService.java @@ -1,11 +1,8 @@ package de.ozgcloud.operator.common.elasticsearch; -import java.io.IOException; - import org.springframework.stereotype.Component; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.ElasticsearchException; import co.elastic.clients.elasticsearch.security.IndicesPrivileges; import co.elastic.clients.elasticsearch.security.PutRoleRequest; import co.elastic.clients.elasticsearch.security.PutUserRequest; @@ -21,22 +18,11 @@ public class ElasticsearchRemoteService { private final ElasticsearchClient client; - public boolean existsIndex(String index) throws Exception { - try { - LOG.debug("{}: Test if elasticsearch index exits.", index); - var exists = client.indices().exists(builder -> builder.index(index)).value(); - LOG.debug("{}: Elasticsearch index exists: {}", index, exists); - return exists; - } catch (ElasticsearchException | IOException e) { - throw new RuntimeException("Error checking index '" + index, e); - } - } - - public void createIndex(String indexName) throws Exception { + public void createOrUpdateIndex(String indexName) throws Exception { try { - LOG.info("{}: Create elasticsearch index", indexName); + LOG.info("{}: Create or update elasticsearch index", indexName); client.indices().create(builder -> builder.index(indexName)); - LOG.info("{}: Create elasticsearch index successful", indexName); + LOG.info("{}: Create or update elasticsearch index successful", indexName); } catch (Exception e) { throw new RuntimeException("Create elasticsearch index " + indexName + "failed.", e); } @@ -102,9 +88,9 @@ public class ElasticsearchRemoteService { public void deleteIndex(String indexName) throws Exception { try { - LOG.info("{}: Delete elasticsearch index", indexName); + LOG.info("{}: Delete elasticsearch index if exists", indexName); client.indices().delete(builder -> builder.index(indexName)); - LOG.info("{}: Delete elasticsearch index successful", indexName); + LOG.info("{}: Delete elasticsearch index if exists successful", indexName); } catch (Exception e) { throw new RuntimeException("Delete elasticsearch index " + indexName + "failed.", e); } @@ -112,9 +98,9 @@ public class ElasticsearchRemoteService { public void deleteSecurityRole(String roleName) throws Exception { try { - LOG.info("{}: Delete elasticsearch role", roleName); + LOG.info("{}: Delete elasticsearch role if exists", roleName); client.security().deleteRole(builder -> builder.name(roleName)); - LOG.info("{}: Delete elasticsearch role successful", roleName); + LOG.info("{}: Delete elasticsearch role if exists successful", roleName); } catch (Exception e) { throw new RuntimeException("Delete elasticsearch role " + roleName + "failed.", e); } @@ -122,9 +108,9 @@ public class ElasticsearchRemoteService { public void deleteSecurityUser(String userName) throws Exception { try { - LOG.info("{}: Delete elasticsearch user", userName); + LOG.info("{}: Delete elasticsearch user if exists", userName); client.security().deleteUser(builder -> builder.username(userName)); - LOG.info("{}: Delete elasticsearch user successful", userName); + LOG.info("{}: Delete elasticsearch user if exists successful", userName); } catch (Exception e) { throw new RuntimeException("Delete elasticsearch user " + userName + "failed.", e); } diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java index e9ac1e2d7e2af811c2fc5bb5f02a23f16291124a..5175eed82d7655fd315ad22d58879aa73812dc26 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/OzgCloudElasticsearchServiceTest.java @@ -114,22 +114,12 @@ class OzgCloudElasticsearchServiceTest { @Nested class TestCreateIndexIfMissing { - @SneakyThrows - @Test - void shouldCheckIfIndexExists() { - service.createIndexIfMissing(NAMESPACE); - - verify(remoteService).existsIndex(NAMESPACE); - } - @SneakyThrows @Test void shouldCreateIndexIfMissing() { - when(remoteService.existsIndex(any())).thenReturn(false); - service.createIndexIfMissing(NAMESPACE); - verify(remoteService).createIndex(NAMESPACE); + verify(remoteService).createOrUpdateIndex(NAMESPACE); } } @@ -236,19 +226,9 @@ class OzgCloudElasticsearchServiceTest { @Nested class TestDeleteSecurityUserIfExists { - @SneakyThrows - @Test - void shouldCheckIfSecurityUserExists() { - service.deleteSecurityUserIfExists(PutUserRequestDataTestFactory.USERNAME); - - verify(remoteService).existsSecurityUser(PutUserRequestDataTestFactory.USERNAME); - } - @SneakyThrows @Test void shouldDeleteSecurityUserIfExists() { - when(remoteService.existsSecurityUser(any())).thenReturn(true); - service.deleteSecurityUserIfExists(PutUserRequestDataTestFactory.USERNAME); verify(remoteService).deleteSecurityUser(PutUserRequestDataTestFactory.USERNAME); @@ -259,19 +239,9 @@ class OzgCloudElasticsearchServiceTest { @Nested class TestDeleteSecurityRoleIfExists { - @SneakyThrows - @Test - void shouldCheckIfSecurityRoleExists() { - service.deleteSecurityRoleIfExists(PutRoleRequestDataTestFactory.NAME); - - verify(remoteService).existsSecurityRole(PutRoleRequestDataTestFactory.NAME); - } - @SneakyThrows @Test void shouldDeleteSecurityRoleIfExists() { - when(remoteService.existsSecurityRole(any())).thenReturn(true); - service.deleteSecurityRoleIfExists(PutRoleRequestDataTestFactory.NAME); verify(remoteService).deleteSecurityRole(PutRoleRequestDataTestFactory.NAME); @@ -284,19 +254,9 @@ class OzgCloudElasticsearchServiceTest { private static final String INDEX_NAME = NAMESPACE; - @SneakyThrows - @Test - void shouldCheckIfIndexExists() { - service.deleteIndexIfExists(INDEX_NAME); - - verify(remoteService).existsIndex(INDEX_NAME); - } - @SneakyThrows @Test void shouldDeleteSecurityRoleIfExists() { - when(remoteService.existsIndex(any())).thenReturn(true); - service.deleteIndexIfExists(INDEX_NAME); verify(remoteService).deleteIndex(INDEX_NAME); diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java index f5914e95c3f53cb8a535ab3677f9cf018eaccbc9..2c850dad36cc8563fbe4024004f32cb76fc07a9a 100644 --- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java +++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/common/elasticsearch/ElasticsearchRemoteServiceITCase.java @@ -21,9 +21,9 @@ import de.ozgcloud.operator.PutUserRequestDataTestFactory; import lombok.SneakyThrows; class ElasticsearchRemoteServiceITCase { - + private static final String INDEX_NAME = "test_index"; - + private final ElasticsearchClient client = ElasticsearchTestClient.create(); private final ElasticsearchRemoteService service = new ElasticsearchRemoteService(client); @@ -31,7 +31,7 @@ class ElasticsearchRemoteServiceITCase { public static void startContainer() { ElasticsearchTestClient.ELASTICSEARCH_CONTAINER.start(); } - + @AfterAll public static void stopContainer() { ElasticsearchTestClient.ELASTICSEARCH_CONTAINER.stop(); @@ -40,105 +40,73 @@ class ElasticsearchRemoteServiceITCase { @DisplayName("Exists index") @Nested class TestExistsIndex { - + @DisplayName("on existing") @Nested class TestOnExisting { - + @SneakyThrows @BeforeEach private void initIndex() { createIndex(); } - + @AfterEach void cleanup() { deleteIndex(); } - - @SneakyThrows - @Test - void shouldReturnTrue() { - var exists = service.existsIndex(INDEX_NAME); - - assertThat(exists).isTrue(); - } - } - - @SneakyThrows - @Test - void shouldReturnFalseIfMissing() { - var exists = service.existsIndex(INDEX_NAME); - - assertThat(exists).isFalse(); } } - + @DisplayName("Create index") @Nested class TestCreateIndex { - + @AfterEach void cleanup() { deleteIndex(); } - + @SneakyThrows @Test void shouldCreateIndex() { - service.createIndex(INDEX_NAME); - + service.createOrUpdateIndex(INDEX_NAME); + assertThat(existsIndex()).isTrue(); } } - + @DisplayName("Exists security role") @Nested class TestExistsSecurityRole { - + @DisplayName("on existing") @Nested class TestOnExisting { - + @SneakyThrows @BeforeEach private void initSecurityRole() { createIndex(); client.security().putRole(service.createPutRoleRequest(PutRoleRequestDataTestFactory.create())); } - + @AfterEach void cleanup() { deleteIndex(); } - - @SneakyThrows - @Test - void shouldReturnTrue() { - var exists = service.existsSecurityRole(PutRoleRequestDataTestFactory.NAME); - - assertThat(exists).isTrue(); - } - } - - @SneakyThrows - @Test - void shouldReturnFalseIfMissing() { - var exists = service.existsSecurityRole(PutRoleRequestDataTestFactory.NAME); - - assertThat(exists).isFalse(); } } - + @DisplayName("Create security role") @Nested class TestCreateSecurityRole { - + @AfterEach void cleanup() { deleteSecurityRole(); } - + @SneakyThrows @Test void shouldCreateSecurityRole() { @@ -146,70 +114,55 @@ class ElasticsearchRemoteServiceITCase { assertThat(existsSecurityRole()).isTrue(); } - + @SneakyThrows private void deleteSecurityRole() { client.security().deleteRole(builder -> builder.name(PutRoleRequestDataTestFactory.NAME)); } } - + @DisplayName("Exists security user") @Nested class TestExistsSecurityUser { - + @DisplayName("on existing") @Nested class TestOnExisting { - + @SneakyThrows @BeforeEach private void initSecurityUser() { createIndex(); client.security().putUser(service.createPutUserRequest(PutUserRequestDataTestFactory.create())); } - + @AfterEach void cleanup() { deleteIndex(); deleteSecurityRole(); } - - @SneakyThrows - @Test - void shouldReturnTrue() { - var exists = service.existsSecurityUser(PutUserRequestDataTestFactory.USERNAME); - - assertThat(exists).isTrue(); - } - } - - @SneakyThrows - @Test - void shouldReturnFalseIfMissing() { - var exists = service.existsSecurityUser(PutUserRequestDataTestFactory.USERNAME); - - assertThat(exists).isFalse(); } } - + @SneakyThrows private void deleteSecurityRole() { client.security().deleteUser(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME)); } + @SneakyThrows private void deleteIndex() { client.indices().delete(builder -> builder.index(INDEX_NAME)); } - + @DisplayName("Create security user") @Nested class TestCreateSecurityUser { - + @AfterEach void cleanup() { deleteSecurityUser(); } - + @SneakyThrows @Test void shouldCreateSecurityUser() { @@ -217,134 +170,134 @@ class ElasticsearchRemoteServiceITCase { assertThat(existsSecurityUser()).isTrue(); } - + @SneakyThrows private boolean existsSecurityUser() { return !client.security().getUser(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME)).result().isEmpty(); } - + @SneakyThrows private void deleteSecurityUser() { client.security().deleteUser(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME)); } } - + @DisplayName("Delete index") @Nested class TestDeleteIndex { - + @BeforeEach void init() { createIndex(); } - + @SneakyThrows @Test - void shouldDeleteIfExists() { + void shouldDeleteIfExists() { service.deleteIndex(INDEX_NAME); - + assertThat(existsIndex()).isFalse(); } } - + @DisplayName("Delete security role") @Nested class TestDeleteSecurityRole { - + @BeforeEach void init() { createIndex(); createSecurityRole(); } - + @AfterEach void cleanup() { deleteIndex(); } - + @SneakyThrows @Test void shouldDeleteIfExists() { assertThat(existsSecurityRole()).isTrue(); - + service.deleteSecurityRole(PutRoleRequestDataTestFactory.NAME); - + assertThat(existsSecurityRole()).isFalse(); } } - + @DisplayName("Delete security user") @Nested class TestDeleteSecurityUser { - + @BeforeEach void init() { createIndex(); createSecurityUser(); } - + @AfterEach void cleanup() { deleteIndex(); } - + @SneakyThrows @Test void shouldDeleteIfExists() { assertThat(existsSecurityUser()).isTrue(); - + service.deleteSecurityUser(PutUserRequestDataTestFactory.USERNAME); - + assertThat(existsSecurityUser()).isFalse(); } } - + @SneakyThrows private boolean existsIndex() { return client.indices().exists(ExistsRequest.of(builder -> builder.index(INDEX_NAME))).value(); } - + @SneakyThrows private void createIndex() { client.indices().create(builder -> builder.index(INDEX_NAME)); } - + @SneakyThrows private void createSecurityRole() { client.security().putRole(this::buildRequest); } - + private PutRoleRequest.Builder buildRequest(PutRoleRequest.Builder requestBuilder) { requestBuilder.name(PutRoleRequestDataTestFactory.NAME); requestBuilder.indices(this::buildIndicesPrivilegesRequest); return requestBuilder; } - + private IndicesPrivileges.Builder buildIndicesPrivilegesRequest(IndicesPrivileges.Builder builder) { builder.names(IndicesPrivilegesDataTestFactory.NAME); builder.privileges(IndicesPrivilegesDataTestFactory.PRIVILEGES); - + return builder; } - + @SneakyThrows private boolean existsSecurityRole() { return !client.security().getRole(builder -> builder.name(PutRoleRequestDataTestFactory.NAME)).result().isEmpty(); } - + @SneakyThrows private void createSecurityUser() { client.security().putUser(this::buildPutUserRequest); } - + private PutUserRequest.Builder buildPutUserRequest(PutUserRequest.Builder builder) { builder.username(PutUserRequestDataTestFactory.USERNAME); builder.roles(PutUserRequestDataTestFactory.ROLES); builder.password(PutUserRequestDataTestFactory.PASSWORD); - + return builder; } - + @SneakyThrows private boolean existsSecurityUser() { return !client.security().getUser(builder -> builder.username(PutUserRequestDataTestFactory.USERNAME)).result().isEmpty(); diff --git a/ozgcloud-keycloak-operator/pom.xml b/ozgcloud-keycloak-operator/pom.xml index 5e7492bcdd821151d02de88ad60524fef2dba323..6c4a4eeb28c84fbef3f2285a2cf16e577fe2f105 100644 --- a/ozgcloud-keycloak-operator/pom.xml +++ b/ozgcloud-keycloak-operator/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>de.ozgcloud</groupId> <artifactId>ozgcloud-operator-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0-SNAPSHOT</version> <relativePath>../</relativePath> </parent> diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/KeycloakResultParser.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/KeycloakResultParser.java index 28e044c19a17e877843f687c1bdcfd2a6e212f71..0d92fac40b9276fe19cf3bf81506bddc865d129d 100644 --- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/KeycloakResultParser.java +++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/KeycloakResultParser.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.core.Response; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapper.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapper.java index 5af876447d55a10bf33180920c1e9d6a9a79fa2a..2c3da928213a93fe77b9d5ea8e8bfb204b255cc2 100644 --- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapper.java +++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapper.java @@ -41,6 +41,7 @@ interface KeycloakRealmMapper { @Mapping(target = "defaultLocale", constant = "de") @Mapping(target = "internationalizationEnabled", constant = "true") @Mapping(target = "passwordPolicy", constant = "upperCase(1) and lowerCase(1) and length(8) and notUsername") + @Mapping(target = "actionTokenGeneratedByUserLifespan", constant = "900") public RealmRepresentation map(OzgCloudKeycloakRealmSpec realm); @Named("supportedLocales") diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteService.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteService.java index b38218f6504b5dc1c0d26f17109151f56695f0c5..2d8faf3a74bc794c4fd229a53a5f7424d7d752bd 100644 --- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteService.java +++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteService.java @@ -24,7 +24,10 @@ package de.ozgcloud.operator.keycloak.user; import java.util.Arrays; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; import org.keycloak.admin.client.CreatedResponseUtil; import org.keycloak.admin.client.Keycloak; @@ -79,16 +82,25 @@ class KeycloakUserRemoteService { } void addClientRoles(String userId, RealmResource realmResource, String namespace, UserRepresentation user) { - user.getClientRoles().keySet().forEach(clientId -> { + getClientNamesOfUser(user).forEach(clientId -> { + var realmClient = getRealmClient(realmResource, clientId); user.getClientRoles().get(clientId).stream() - .map(clientRoleName -> keycloakGenericRemoteService.getClientRole(clientRoleName, realmClient.getId(), namespace) - .orElseThrow(() -> new KeycloakException( - "Role " + clientRoleName + " not found for client with clientId " + clientId + " in realm " + namespace))) + .map(clientRoleName -> getClientRole(namespace, clientId, realmClient, clientRoleName)) .forEach(clientRole -> addClientRoleToUser(clientRole, realmResource, userId, realmClient)); }); } + Stream<String> getClientNamesOfUser(UserRepresentation user) { + return Optional.ofNullable(user.getClientRoles()).map(Map::keySet).map(Set::stream).orElse(Stream.empty()); + } + + RoleRepresentation getClientRole(String namespace, String clientId, ClientRepresentation realmClient, String clientRoleName) { + return keycloakGenericRemoteService.getClientRole(clientRoleName, realmClient.getId(), namespace) + .orElseThrow(() -> new KeycloakException( + "Role " + clientRoleName + " not found for client with clientId " + clientId + " in realm " + namespace)); + } + ClientRepresentation getRealmClient(RealmResource realmResource, String clientId) { return realmResource.clients() .findByClientId(clientId).stream().findFirst() diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserService.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserService.java index c8343f80700a4d031455c212a3e7ce5a6896378f..b189ad0186589dcc3f7c281a32a1d3861ee8f742 100644 --- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserService.java +++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/KeycloakUserService.java @@ -26,6 +26,7 @@ package de.ozgcloud.operator.keycloak.user; import java.util.Optional; import org.apache.commons.lang3.StringUtils; +import org.keycloak.representations.idm.UserRepresentation; import org.springframework.stereotype.Component; import lombok.RequiredArgsConstructor; @@ -42,14 +43,28 @@ class KeycloakUserService { public void createOrUpdateUser(OzgCloudKeycloakUserSpec userSpec, String namespace) { + createAndSetUserPasswordIfNotExists(userSpec, namespace); + + remoteService.getUserByName(userSpec.getKeycloakUser().getUsername(), namespace) + .ifPresentOrElse(existingUser -> updateUser(userSpec, namespace, existingUser), + () -> createUser(userSpec, namespace)); + } + + void createAndSetUserPasswordIfNotExists(OzgCloudKeycloakUserSpec userSpec, String namespace) { if (userHasNoPassword(userSpec, namespace)) { var secret = userSecretService.getOrCreateClusterSecret(userSpec, namespace); userSpec.getKeycloakUser().setPassword(userSecretService.getPasswordFromSecret(secret)); } + } - remoteService.getUserByName(userSpec.getKeycloakUser().getUsername(), namespace) - .ifPresentOrElse(existingUser -> remoteService.updateUser(userMapper.update(existingUser, userSpec), namespace), - () -> remoteService.createUser(userMapper.map(userSpec), namespace)); + void updateUser(OzgCloudKeycloakUserSpec userSpec, String namespace, UserRepresentation existingUser) { + if (userSpec.isUpdateUser()) { + remoteService.updateUser(userMapper.update(existingUser, userSpec), namespace); + } + } + + void createUser(OzgCloudKeycloakUserSpec userSpec, String namespace) { + remoteService.createUser(userMapper.map(userSpec), namespace); } boolean userHasNoPassword(OzgCloudKeycloakUserSpec userSpec, String namespace) { diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpec.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpec.java index f6cf222c1c71eae502b81bc983fad6cd0249e559..f38ec6684a2828684333aee496fb5f5611477589 100644 --- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpec.java +++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpec.java @@ -48,6 +48,9 @@ class OzgCloudKeycloakUserSpec { @JsonProperty("keep_after_delete") private boolean keepAfterDelete; + @JsonProperty("update_user") + private boolean updateUser; + @JsonProperty("keycloak_user") private KeycloakUserSpecUser keycloakUser; diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/client/KeycloakClientRemoteServiceTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/client/KeycloakClientRemoteServiceTest.java index 56b8a2c18128483b414bcafa8f87d9cb0e501447..2a2337e196e5316e74f6d856a06bf8f243d3fd0e 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/client/KeycloakClientRemoteServiceTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/client/KeycloakClientRemoteServiceTest.java @@ -26,7 +26,7 @@ package de.ozgcloud.operator.keycloak.client; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/group/KeycloakGroupRemoteServiceTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/group/KeycloakGroupRemoteServiceTest.java index 1303467ed34a87703ea569e4f7547c3590930b55..1bb10c9e0b8169c4409ed987c19f2f4dbb204b14 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/group/KeycloakGroupRemoteServiceTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/group/KeycloakGroupRemoteServiceTest.java @@ -30,7 +30,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapperTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapperTest.java index 92de72339804e82685cef9601a9bbc983d068ebe..ddb2e9ab9fb47e512906eb0d9ffd96ae5e9cde75 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapperTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/realm/KeycloakRealmMapperTest.java @@ -82,4 +82,11 @@ class KeycloakRealmMapperTest { assertThat(mapped.getPasswordPolicy()).isEqualTo("upperCase(1) and lowerCase(1) and length(8) and notUsername"); } + + @Test + void shouldSetActionTokenGeneratedByUserLifespan() { + var mapped = mapper.map(OzgCloudKeycloakRealmSpecTestFactory.create()); + + assertThat(mapped.getActionTokenGeneratedByUserLifespan()).isEqualTo(900); + } } diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakLivelTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakLivelTest.java index b43f2a316927c57f42800c83a5240f4f34a6044d..fb6cfcdea02ce6af9173de162ee5cd28dcc668c6 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakLivelTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakLivelTest.java @@ -23,8 +23,12 @@ */ package de.ozgcloud.operator.keycloak.user; +import static org.assertj.core.api.Assertions.*; + +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.commons.lang3.reflect.FieldUtils; import org.junit.jupiter.api.Disabled; @@ -35,13 +39,22 @@ import org.keycloak.representations.idm.UserRepresentation; import org.mockito.InjectMocks; import org.mockito.Spy; +import de.ozgcloud.operator.keycloak.KeycloakGenericRemoteService; + @Disabled("Should only be used manually") class KeycloakLivelTest { + private static final String TESTNAMESPACE = "by-torsten-dev"; + private static final String TESTUSERNAME = "hans"; + @Spy @InjectMocks private KeycloakUserRemoteService userRemoteService; + @Spy + @InjectMocks + private KeycloakGenericRemoteService keycloakGenericRemoteService; + @Test void testReal() throws IllegalAccessException { Keycloak kc = KeycloakBuilder.builder() @@ -56,15 +69,26 @@ class KeycloakLivelTest { FieldUtils.writeField(userRemoteService, "keycloak", kc, true); // when(keycloakClient.getKeycloak()).thenReturn(kc); - userRemoteService.createUser(createUser(), "by-torsten-ozgcloud-keycloak-operator-dev"); +// userRemoteService.createUser(createUser(), "by-torsten-dev"); + + Optional<UserRepresentation> user = userRemoteService.getUserByName(TESTUSERNAME, TESTNAMESPACE); + assertThat(user).isPresent(); + UserRepresentation u = user.get(); + u.setCredentials(Collections.emptyList()); + u.setEmail("updated-hans@glueck.local"); + userRemoteService.updateUser(u, TESTNAMESPACE); } private UserRepresentation createUser() { UserRepresentation u = new UserRepresentation(); - u.setUsername("hans"); + u.setUsername(TESTUSERNAME); u.setGroups(List.of("Bauamt")); u.setClientRoles(Map.of("alfa", List.of("VERWALTUNG_USER"))); + u.setEnabled(true); + u.setEmail("hans@glueck.local1"); + u.setClientRoles(Collections.emptyMap()); +// u.setCredentials(); return u; } } diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteServiceTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteServiceTest.java index 70fd40079ca06c1e92fb78719b2a93322be950a5..67693d1cd2b589a37f2872e316f404ae17806c5a 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteServiceTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserRemoteServiceTest.java @@ -32,7 +32,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import javax.ws.rs.core.Response; +import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -61,6 +61,7 @@ class KeycloakUserRemoteServiceTest { private final static String REALM = "TestRealm"; private final static String USERID = "UserId"; private final static String CLIENT_ID = "ClientId"; + private final static String CLIENT_ROLE_NAME = "ClientRoleName"; @Spy @InjectMocks @@ -173,7 +174,6 @@ class KeycloakUserRemoteServiceTest { @Test void shouldThrowOnMissingClientRole() { var user = UserRepresentationTestFactory.create(); - userRemoteService.addClientRoles(USERID, realmResource, REALM, userRepresentation); when(genericRemoteService.getClientRole(any(), any(), any())).thenReturn(Optional.empty()); assertThrows(KeycloakException.class, @@ -181,6 +181,69 @@ class KeycloakUserRemoteServiceTest { } } + @Nested + class TestAddClientRolesUserWithoutRoles { + + @Test + void shouldNotThrowOnUserWithoutRoles() { + UserRepresentation user = createUserWithNullRoles(); + + assertDoesNotThrow(() -> userRemoteService.addClientRoles(USERID, realmResource, REALM, user)); + } + + private UserRepresentation createUserWithNullRoles() { + UserRepresentation user = UserRepresentationTestFactory.create(); + user.setClientRoles(null); + return user; + } + } + + @Nested + class TestGetRealmClientNamesOfUser { + + @Test + void shouldReturnClientNames() { + UserRepresentation user = UserRepresentationTestFactory.create(); + + List<String> clientNames = userRemoteService.getClientNamesOfUser(user).toList(); + + assertThat(clientNames).contains(UserRepresentationTestFactory.CLIENT_NAME); + } + } + + @Nested + class TestGetClientRole { + + @Spy + @InjectMocks + private KeycloakUserRemoteService userRemoteService; + + @Mock + private KeycloakGenericRemoteService keycloakGenericRemoteService; + + @BeforeEach + void init() { + when(clientRepresentation.getId()).thenReturn(CLIENT_ID); + } + + @Test + void shouldReturnClientRole() { + when(keycloakGenericRemoteService.getClientRole(CLIENT_ROLE_NAME, CLIENT_ID, REALM)).thenReturn(Optional.of(roleRepresentation)); + + RoleRepresentation role = userRemoteService.getClientRole(REALM, CLIENT_ID, clientRepresentation, CLIENT_ROLE_NAME); + + assertThat(role).isEqualTo(roleRepresentation); + } + + @Test + void shouldThrowOnMissingRole() { + when(keycloakGenericRemoteService.getClientRole(CLIENT_ROLE_NAME, CLIENT_ID, REALM)).thenReturn(Optional.empty()); + + assertThrows(KeycloakException.class, + () -> userRemoteService.getClientRole(REALM, CLIENT_ID, clientRepresentation, CLIENT_ROLE_NAME)); + } + } + @Nested class TestAddClientRoleToUser { diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserServiceTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserServiceTest.java index 827bbb9eff01c698e1b5f9d557c12bedce12f11f..75ced4033b010aedb21b69504b68a27ef76c3163 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserServiceTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/KeycloakUserServiceTest.java @@ -39,7 +39,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.Spy; import io.fabric8.kubernetes.api.model.Secret; @@ -72,35 +71,58 @@ class KeycloakUserServiceTest { @Captor private ArgumentCaptor<OzgCloudKeycloakUserSpec> ozgCloudKeycloakUserSpecCaptor; - private final OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + @Test + void shouldCallCreateAndSetUserPasswordIfNotExists() { + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); - @DisplayName("user has no password") - @Nested - class TestOnUserHasNoPassword { + service.createOrUpdateUser(userSpec, TEST_NAMESPACE); - @BeforeEach - void mock() { - doReturn(true).when(service).userHasNoPassword(any(), eq(TEST_NAMESPACE)); - } + verify(service).createAndSetUserPasswordIfNotExists(userSpec, TEST_NAMESPACE); + } - @Test - void shouldGetOrCreateClusterSecret() { - service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + @Test + void shouldCallUserRemoteServiceGetUserByName() { + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); - verify(userSecretService).getOrCreateClusterSecret(userSpec, TEST_NAMESPACE); - } + service.createOrUpdateUser(userSpec, TEST_NAMESPACE); - @Test - void shouldUpdateUserPassword() { - var userWithoutPassword = OzgCloudKeycloakUserSpecTestFactory.createBuilder() - .keycloakUser(KeycloakUserSpecUserTestFactory.createBuiler().password(StringUtils.EMPTY).build()).build(); - when(userSecretService.getPasswordFromSecret(any())).thenReturn(KeycloakUserSpecUserTestFactory.PASSWORD); + verify(remoteService).getUserByName(KeycloakUserSpecUserTestFactory.USERNAME, TEST_NAMESPACE); + } - service.createOrUpdateUser(userWithoutPassword, TEST_NAMESPACE); + @Test + void shouldCallCreateUserIfNotExists() { + var userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + when(remoteService.getUserByName(KeycloakUserSpecUserTestFactory.USERNAME, TEST_NAMESPACE)) + .thenReturn(Optional.empty()); - verify(userMapper).map(ozgCloudKeycloakUserSpecCaptor.capture()); - assertThat(ozgCloudKeycloakUserSpecCaptor.getValue().getKeycloakUser().getPassword()).isEqualTo(KeycloakUserSpecUserTestFactory.PASSWORD); - } + service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + + verify(service).createUser(userSpec, TEST_NAMESPACE); + } + + @Test + void shouldCallUpdateUserIfAlreadyExists() { + var userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + var remoteUser = UserRepresentationTestFactory.create(); + when(remoteService.getUserByName(KeycloakUserSpecUserTestFactory.USERNAME, TEST_NAMESPACE)) + .thenReturn(Optional.of(remoteUser)); + + service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + + verify(service).updateUser(userSpec, TEST_NAMESPACE, remoteUser); + } + } + + @Nested + class TestCreateAndSetUserPasswordIfNotExists { + + @Test + void shouldCallUserHasNoPassword() { + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + + service.createAndSetUserPasswordIfNotExists(userSpec, TEST_NAMESPACE); + + verify(service).userHasNoPassword(userSpec, TEST_NAMESPACE); } @DisplayName("on user has password") @@ -114,57 +136,54 @@ class KeycloakUserServiceTest { @Test void shouldNotReadSecretFromCluster() { - service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + + service.createAndSetUserPasswordIfNotExists(userSpec, TEST_NAMESPACE); - verify(userSecretService, never()).create(userSpec, TEST_NAMESPACE); + verify(userSecretService, never()).getOrCreateClusterSecret(userSpec, TEST_NAMESPACE); } - } - @Test - void shouldCallUserHasNoPassword() { - service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + @Test + void shouldNotCallUserSecretServiceGetOrCreateClusterSecret() { + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); - verify(service).userHasNoPassword(userSpec, TEST_NAMESPACE); - } + service.createAndSetUserPasswordIfNotExists(userSpec, TEST_NAMESPACE); - @Test - void shouldCallUserMapper() { - service.createOrUpdateUser(userSpec, TEST_NAMESPACE); - - verify(userMapper).map(userSpec); + verify(userSecretService, never()).getPasswordFromSecret(any(Secret.class)); + } } - @Test - void shouldCallUserRemoteServiceGetUserByName() { - var userRepresentation = UserRepresentationTestFactory.create(); - - service.createOrUpdateUser(userSpec, TEST_NAMESPACE); + @DisplayName("user has no password") + @Nested + class TestOnUserHasNoPassword { - verify(remoteService).getUserByName(userRepresentation.getUsername(), TEST_NAMESPACE); - } + @BeforeEach + void mock() { + doReturn(true).when(service).userHasNoPassword(any(), eq(TEST_NAMESPACE)); + } - @Test - void shouldCreateUserIfNotExists() { - when(remoteService.getUserByName(KeycloakUserSpecUserTestFactory.USERNAME, TEST_NAMESPACE)) - .thenReturn(Optional.empty()); - when(userMapper.map(any())).thenReturn(Mockito.mock(UserRepresentation.class)); + @Test + void shouldGetOrCreateClusterSecret() { + OzgCloudKeycloakUserSpec userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); - service.createOrUpdateUser(OzgCloudKeycloakUserSpecTestFactory.create(), TEST_NAMESPACE); + service.createAndSetUserPasswordIfNotExists(userSpec, TEST_NAMESPACE); - verify(remoteService).createUser(any(UserRepresentation.class), eq(TEST_NAMESPACE)); - } + verify(userSecretService).getOrCreateClusterSecret(userSpec, TEST_NAMESPACE); + } - @Test - void shouldUpdateUserIfExists() { - var userRepresentation = Mockito.mock(UserRepresentation.class); - when(remoteService.getUserByName(KeycloakUserSpecUserTestFactory.USERNAME, TEST_NAMESPACE)) - .thenReturn(Optional.of(userRepresentation)); - when(userMapper.update(eq(userRepresentation), any())).thenReturn(userRepresentation); + @Test + void shouldUpdateUserPassword() { + String NEWPASSWORD = "NewPassword"; + var userWithoutPassword = OzgCloudKeycloakUserSpecTestFactory.createBuilder() + .keycloakUser(KeycloakUserSpecUserTestFactory.createBuiler().password(StringUtils.EMPTY).build()).build(); + when(userSecretService.getPasswordFromSecret(any())).thenReturn(NEWPASSWORD); - service.createOrUpdateUser(OzgCloudKeycloakUserSpecTestFactory.create(), TEST_NAMESPACE); + service.createAndSetUserPasswordIfNotExists(userWithoutPassword, TEST_NAMESPACE); - verify(remoteService).updateUser(userRepresentation, TEST_NAMESPACE); + assertThat(userWithoutPassword.getKeycloakUser().getPassword()).isEqualTo(NEWPASSWORD); + } } + } @DisplayName("Test user has no password") @@ -197,6 +216,46 @@ class KeycloakUserServiceTest { } } + @Nested + class TestCreateUser { + + @Test + void shouldCallRemoteServiceCreateUser() { + var userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); + when(userMapper.map(userSpec)).thenReturn(userRepresentation); + + service.createUser(userSpec, TEST_NAMESPACE); + + verify(remoteService).createUser(userRepresentation, TEST_NAMESPACE); + } + } + + @Nested + class TestUpdateUser { + + @Test + void shouldUpdateUserIfEnabled() { + var userSpec = OzgCloudKeycloakUserSpecTestFactory.create(); + UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); + when(userMapper.update(userRepresentation, userSpec)).thenReturn(userRepresentation); + + service.updateUser(userSpec, TEST_NAMESPACE, userRepresentation); + + verify(remoteService).updateUser(any(UserRepresentation.class), eq(TEST_NAMESPACE)); + } + + @Test + void shouldNotUpdateUserIfDisabled() { + var userSpec = OzgCloudKeycloakUserSpecTestFactory.createBuilder() + .updateUser(false).build(); + + service.updateUser(userSpec, TEST_NAMESPACE, UserRepresentationTestFactory.create()); + + verify(remoteService, never()).updateUser(null, TEST_NAMESPACE); + } + } + @Nested class TestDeleteUser { diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpecTestFactory.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpecTestFactory.java index a76206d878e3c9a3e240b47f037990787dca16de..2418ed24fb2edc226edea0c03502d844bbb68ef4 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpecTestFactory.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/OzgCloudKeycloakUserSpecTestFactory.java @@ -27,12 +27,15 @@ import de.ozgcloud.operator.keycloak.user.OzgCloudKeycloakUserSpec.OzgCloudKeycl public class OzgCloudKeycloakUserSpecTestFactory { + public static final boolean UPDATE_USER = true; + public static OzgCloudKeycloakUserSpec create() { return createBuilder().build(); } public static OzgCloudKeycloakUserSpecBuilder createBuilder() { return OzgCloudKeycloakUserSpec.builder() + .updateUser(UPDATE_USER) .keycloakUser(KeycloakUserSpecUserTestFactory.create()); } } diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/UserSecretBuilderTest.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/UserSecretBuilderTest.java index 0cc1d435be4aa4ae3b05cc6fe6f69abafd994087..3473c34450878c93d26e324c902cdc80d1be12c3 100644 --- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/UserSecretBuilderTest.java +++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/keycloak/user/UserSecretBuilderTest.java @@ -102,6 +102,13 @@ class UserSecretBuilderTest { assertThat(password).isAlphanumeric(); } + @Test + void shouldHaveMiminumLength() { + var password = decode(builder.generatePassword()); + + assertThat(password).hasSize(8); + } + @Test void shouldEncode() { builder.generatePassword(); diff --git a/pom.xml b/pom.xml index 8e7c22efc885c6c1e4ca3f8b4671d312eda90d56..43a48680d9dfdcd14e4283d4c10af48b05d4d4fa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,13 @@ <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> - <version>3.1.7</version> + <version>3.1.8</version> <relativePath/> </parent> <groupId>de.ozgcloud</groupId> <artifactId>ozgcloud-operator-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0-SNAPSHOT</version> <packaging>pom</packaging> <name>OzgCloud Operator Parent</name> @@ -23,20 +23,20 @@ </modules> <properties> - <spring-boot.version>3.1.7</spring-boot.version> + <spring-boot.version>3.1.8</spring-boot.version> <operator-sdk.version>5.4.1</operator-sdk.version> <!-- tools --> <commons-beanutils.version>1.9.4</commons-beanutils.version> <lombok.version>1.18.28</lombok.version> <mapstruct.version>1.5.5.Final</mapstruct.version> - <keycloak-adapter.version>20.0.5</keycloak-adapter.version> + <keycloak-adapter.version>23.0.5</keycloak-adapter.version> <reflections.version>0.10.2</reflections.version> <validation-api.version>2.0.1.Final</validation-api.version> <lorem.version>2.2</lorem.version> <!-- test --> - <junit-jupiter.version>5.9.3</junit-jupiter.version> + <junit-jupiter.version>5.10.1</junit-jupiter.version> <kubernetes-server-mock.version>6.9.2</kubernetes-server-mock.version> <io.javaoperatorsdk.version>0.9.5</io.javaoperatorsdk.version>