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>