diff --git a/ozgcloud-elastic-operator/pom.xml b/ozgcloud-elastic-operator/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6df5d09797cf903fb45bf384013c2baf142c6868
--- /dev/null
+++ b/ozgcloud-elastic-operator/pom.xml
@@ -0,0 +1,71 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.ozgcloud</groupId>
+		<artifactId>ozgcloud-operator-parent</artifactId>
+		<version>0.0.1-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>ozgcloud-elastic-operator</artifactId>
+	<name>OzgCloud Elastic Operator</name>
+	<description>OzgCloud Elastic Operator</description>
+
+	<dependencies>
+		<!-- keycloak -->
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-admin-client</artifactId>
+		</dependency>
+	
+		<!-- TOCHECK: werden die gebraucht!? -->
+		<dependency>
+			<groupId>javax.validation</groupId>
+			<artifactId>validation-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>jakarta.xml.bind</groupId>
+			<artifactId>jakarta.xml.bind-api</artifactId>
+			<version>4.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.reflections</groupId>
+			<artifactId>reflections</artifactId>
+		</dependency>
+		<!-- TOCHECK -->
+
+		<!-- spring -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+		</dependency>
+		
+		<!-- tools -->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+		</dependency>
+		
+		<!-- test -->
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-engine</artifactId>
+			<version>5.9.3</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-params</artifactId>
+			<version>5.9.3</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+		    <groupId>io.fabric8</groupId>
+		    <artifactId>kubernetes-server-mock</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	
+</project>
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/CustomResourceStatus.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/CustomResourceStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ef66d5c501cc50d1d8dbf0e3ac323f0df118e99
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/CustomResourceStatus.java
@@ -0,0 +1,5 @@
+package de.ozgcloud.operator;
+
+public enum CustomResourceStatus {
+	OK, IN_PROGRESS, ERROR;
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticCustomResourceStatus.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticCustomResourceStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cf85a9cda3eec2c7896e5d6fe4c3cc188e3c206
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticCustomResourceStatus.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.operator;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ElasticCustomResourceStatus extends ObservedGenerationAwareStatus {
+
+	private CustomResourceStatus status;
+
+	private String message;
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticOperatorApplication.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticOperatorApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c35d6d4fe7f34dba321603dbc7d22be3ec417b4
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/ElasticOperatorApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.operator;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ElasticOperatorApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(ElasticOperatorApplication.class, args);
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/OperatorConfig.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/OperatorConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..88044785406f57bbd730238694b40b9655f7d3d2
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/OperatorConfig.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.operator;
+
+import java.time.Duration;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.javaoperatorsdk.operator.Operator;
+import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+
+@Configuration
+public class OperatorConfig {
+
+	public static final Duration RECONCILER_RETRY_SECONDS = Duration.ofSeconds(20);
+	public static final Duration RECONCILER_RETRY_SECONDS_ON_ERROR = Duration.ofSeconds(60);
+
+	@Bean(initMethod = "start", destroyMethod = "stop")
+	@SuppressWarnings("rawtypes")
+	Operator operator(List<Reconciler> controllers) {
+		var operator = new Operator();
+		controllers.forEach(operator::register);
+		return operator;
+	}
+}
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef03ab17b6676cec9ce0c5c3e0718180aa18e8f0
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/common/kubernetes/KubernetesService.java
@@ -0,0 +1,184 @@
+package de.ozgcloud.operator.common.kubernetes;
+
+import java.util.Objects;
+
+import org.springframework.stereotype.Component;
+
+import io.fabric8.kubernetes.api.model.EnvVar;
+import io.fabric8.kubernetes.api.model.EnvVarBuilder;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.batch.v1.Job;
+import io.fabric8.kubernetes.api.model.batch.v1.JobBuilder;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Component
+public class KubernetesService {
+
+	private final KubernetesClient client;
+
+	public boolean existNamespace(String namespace) {
+		return Objects.nonNull(client.namespaces().withName(namespace).get());
+	}
+
+	public Resource<Secret> getSecretResource(String namespace, String name) {
+		return client.secrets().inNamespace(namespace).withName(name);
+	}
+	
+	
+	//PoC
+	public Pod doInPod(String namespace, String podName) {
+
+//        client.batch().v1().jobs().inNamespace(namespace).createOrReplace(job);
+		client.batch().v1().raw(podName);
+		
+		
+		return client.pods().inNamespace(namespace).withName(podName).get();
+	}
+	
+	public void executeJob(String namespace) {
+		var ELASTIC_USER_SECRET_NAME = "ozg-search-cluster-es-elastic-user";
+		var ELASTIC_SYSTEM_NAMESPACE = "elastic-system";
+		var ELASTIC_USER_SECRET_ELASTIC = "elastic";
+		var secretResource = getSecretResource(ELASTIC_SYSTEM_NAMESPACE, ELASTIC_USER_SECRET_NAME);
+		
+		if(Objects.isNull(secretResource.get())) {
+			//Error - elastic-system namespace secret not exists
+		}
+			
+		
+		var password = secretResource.get().getStringData().get(ELASTIC_USER_SECRET_ELASTIC);
+		var jobEnvs = buildEnvVars(namespace, password);
+	}
+		
+	private Job buildJob(String jobName) {
+		return new JobBuilder()
+	            .withApiVersion("batch/v1")
+	            .withNewMetadata()
+	            .withName(jobName)
+	            .endMetadata()
+	            .withNewSpec()
+	            .withBackoffLimit(4)//TOCHECK: notwendig? wofür?
+	            .withNewTemplate()
+	            .withNewSpec()
+	            .withRestartPolicy("Never")
+	            //containers START
+	            .addNewContainer()
+	            .withName("es-create-access")
+	            .withImage("manusant/curl-jq")
+	            .withEnv(buildEnvVars("password", "namespace"))
+	            
+	            
+	            
+	            
+	            .withCommand("/bin/sh", "-c")
+	            .withArgs("echo \"Job started\"; i=1; while [ $i -le $MAX_COUNT ]; do echo $i; i=$((i+1)) ; sleep 1;done; echo \"Job Done!\"")
+	            .endContainer()
+	            //containers END
+	            .endSpec()
+	            .endTemplate()
+	            .endSpec().build();
+	}
+	
+	static final String ELASTICSEARCH_NAMESPACE_PASSWORD_FIELD = "ES_NS_PASSWORD";
+	static final String ELASTICSEARCH_NAMESPACE_USER_FIELD = "ES_NS_USER";
+	static final String ELASTICSEARCH_CLUSTER_FIELD = "ES_CLUSTER";
+	static final String ELASTICSEARCH_PASSWORD_FIELD = "ELASTICSEARCH_PASSWORD";
+	
+	private EnvVar buildEnvVars(String namespace, String password) {
+//		 - name: ES_NS_PASSWORD
+//       value: "{{ elasticsearch_user_password }}"
+//     - name: ES_NS_USER
+//       value: "{{ kommune }}"
+//     - name: ES_CLUSTER
+//       value: "{{ kommune }}"
+//     - name: ELASTICSEARCH_PASSWORD
+//       valueFrom:
+//         secretKeyRef:
+//           name: ozg-search-cluster-es-elastic-user
+//           key: elastic
+//   command:
+		return new EnvVarBuilder()
+				.withName(ELASTICSEARCH_NAMESPACE_PASSWORD_FIELD).withValue(password)
+				.withName(ELASTICSEARCH_NAMESPACE_USER_FIELD).withValue(namespace)
+				.withName(ELASTICSEARCH_CLUSTER_FIELD).withValue(namespace)
+				.withName(ELASTICSEARCH_PASSWORD_FIELD).withValue(password)
+				.build();
+	}
+}
+
+
+//apiVersion: batch/v1
+//kind: Job
+//metadata:
+//  name: es-create-access-{{ kommune }}
+//spec:
+//  parallelism: 1
+//  completions: 1
+//  template:
+//    metadata:
+//      name: es-create-access-{{ kommune }}
+//    spec:
+//      restartPolicy: Never
+//      containers:
+//        - name: es-create-access
+//          image: manusant/curl-jq
+//          env:
+//            - name: ES_NS_PASSWORD
+//              value: "{{ elasticsearch_user_password }}"
+//            - name: ES_NS_USER
+//              value: "{{ kommune }}"
+//            - name: ES_CLUSTER
+//              value: "{{ kommune }}"
+//            - name: ELASTICSEARCH_PASSWORD
+//              valueFrom:
+//                secretKeyRef:
+//                  name: ozg-search-cluster-es-elastic-user
+//                  key: elastic
+//          command:
+//            - /bin/sh
+//            - -c
+//            - |
+//              curl -k -X PUT -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/'$ES_NS_USER
+//      initContainers:
+//        - name: create-es-role
+//          image: manusant/curl-jq
+//          env:
+//            - name: ES_NS_PASSWORD
+//              value: "{{ elasticsearch_user_password }}"
+//            - name: ES_NS_USER
+//              value: "{{ kommune }}"
+//            - name: ES_CLUSTER
+//              value: "{{ kommune }}"
+//            - name: ELASTICSEARCH_PASSWORD
+//              valueFrom:
+//                secretKeyRef:
+//                  name: ozg-search-cluster-es-elastic-user
+//                  key: elastic
+//          command:
+//            - /bin/sh
+//            - -c
+//            - |
+//              curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/_security/role/'$ES_NS_USER -d '{ "indices": [ { "names": [ "'$ES_NS_USER'*" ], "privileges": ["all"] } ] }'
+//        - name: create-es-user
+//          image: manusant/curl-jq
+//          env:
+//            - name: ES_NS_PASSWORD
+//              value: "{{ elasticsearch_user_password }}"
+//            - name: ES_NS_USER
+//              value: "{{ kommune }}"
+//            - name: ES_CLUSTER
+//              value: "{{ kommune }}"
+//            - name: ELASTICSEARCH_PASSWORD
+//              valueFrom:
+//                secretKeyRef:
+//                  name: ozg-search-cluster-es-elastic-user
+//                  key: elastic
+//          command:
+//            - /bin/sh
+//            - -c
+//            - |
+//              curl -k -X POST -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/_security/user/'$ES_NS_USER -d '{"password" : "'$ES_NS_PASSWORD'" ,"roles" : [ "'$ES_NS_USER'" ]}'
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserCustomResource.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserCustomResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0f02a31f05e8c54fe554073b4753759793f0734
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserCustomResource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.operator.user;
+
+import de.ozgcloud.operator.ElasticCustomResourceStatus;
+import io.fabric8.kubernetes.api.model.Namespaced;
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.Kind;
+import io.fabric8.kubernetes.model.annotation.Plural;
+import io.fabric8.kubernetes.model.annotation.Singular;
+import io.fabric8.kubernetes.model.annotation.Version;
+
+@Kind("OzgCloudElasticUser")
+@Group("operator.ozgcloud.de")
+@Version("v1")
+@Singular("ozgcloudelasticuser")
+@Plural("ozgcloudelasticusers")
+@SuppressWarnings("serial")
+class ElasticUserCustomResource extends CustomResource<ElasticUserSpec, ElasticCustomResourceStatus> implements Namespaced {
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserReconciler.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserReconciler.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c37257978d7f7256e9fefeca020ec7c39be9c10
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserReconciler.java
@@ -0,0 +1,26 @@
+package de.ozgcloud.operator.user;
+
+import org.springframework.stereotype.Component;
+
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.java.Log;
+
+@Log
+@RequiredArgsConstructor
+@ControllerConfiguration
+@Component
+public class ElasticUserReconciler implements Reconciler<ElasticUserCustomResource> {
+
+	private final ElasticUserService service;
+
+	@Override
+	public UpdateControl<ElasticUserCustomResource> reconcile(ElasticUserCustomResource resource, Context<ElasticUserCustomResource> context)
+			throws Exception {
+		log.info("Reconcile user: " + resource.getCRDName());
+		return service.checkSecret(resource, context);
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSecretBuilder.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSecretBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4f9efedca845f5ba163a6b5e46f27d890ca0486
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSecretBuilder.java
@@ -0,0 +1,41 @@
+package de.ozgcloud.operator.user;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.stereotype.Component;
+
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.SecretBuilder;
+
+@Component
+class ElasticUserSecretBuilder {
+
+	static final String SECRET_TYPE = "Opaque";
+	static final String SECRET_ADDRESS_FIELD = "address";
+	static final String SECRET_INDEX_FIELD = "index";
+	static final String SECRET_PASSWORD_FIELD = "password";
+	static final String SECRET_USERNAME_FIELD = "username";
+
+	static final String SECRET_ADDRESS_VALUE = "ozg-search-cluster-es-http.elastic-system:9200";
+	static final int PASSWORD_LENGTH = 15;
+
+	public Secret build(ElasticUserCustomResource resource, String name) {
+		var namespace = resource.getMetadata().getNamespace();
+		return new SecretBuilder()
+				.withType(SECRET_TYPE)
+				.withMetadata(createMetaData(name, namespace))
+				.addToStringData(SECRET_ADDRESS_FIELD, SECRET_ADDRESS_VALUE)
+				.addToStringData(SECRET_INDEX_FIELD, namespace)
+				.addToStringData(SECRET_PASSWORD_FIELD, RandomStringUtils.randomAlphabetic(PASSWORD_LENGTH))
+				.addToStringData(SECRET_USERNAME_FIELD, namespace)
+				.build();
+	}
+
+	private ObjectMeta createMetaData(String name, String namespace) {
+		var metadata = new ObjectMeta();
+		metadata.setName(name);
+		metadata.setNamespace(namespace);
+
+		return metadata;
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserService.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..71324cbb538d86aa11a3bac6d772818532f86887
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserService.java
@@ -0,0 +1,68 @@
+package de.ozgcloud.operator.user;
+
+import java.util.Objects;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.operator.CustomResourceStatus;
+import de.ozgcloud.operator.OperatorConfig;
+import de.ozgcloud.operator.common.kubernetes.KubernetesService;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import io.fabric8.kubernetes.client.extension.ResourceAdapter;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.java.Log;
+
+@Log
+@RequiredArgsConstructor
+@Component
+class ElasticUserService {
+
+	static final String ELASTIC_USER_SECRET_NAME = "elasticsearch-credentials";
+
+	private final ElasticUserSecretBuilder secretBuilder;
+
+	private final KubernetesService kubernetesService;
+
+	public UpdateControl<ElasticUserCustomResource> checkSecret(ElasticUserCustomResource resource, Context<ElasticUserCustomResource> context) {
+		try {
+			log.info("Check secret...");
+			var secretResource = getSecretResource(resource);
+			if (Objects.isNull(secretResource.get())) {
+				log.info("Secret not exists, create one...");
+				
+				createAdapter(secretResource).create(secretBuilder.build(resource, ELASTIC_USER_SECRET_NAME));
+				
+				log.info("Secret creation successful.");
+			}
+			return ElasticUserUpdateControlBuilder.fromResource(resource).withStatus(CustomResourceStatus.OK).build();
+		} catch (Exception e) {
+			log.info("Secret creation failed: " + e);
+			return buildExceptionUpdateControl(resource, e);
+		}
+	}
+
+	private Resource<Secret> getSecretResource(ElasticUserCustomResource resource) {
+		return kubernetesService.getSecretResource(resource.getMetadata().getNamespace(), ELASTIC_USER_SECRET_NAME);
+	}
+	
+	ResourceAdapter<Secret> createAdapter(Resource<Secret> resource) {
+		return new ResourceAdapter<Secret>(resource);
+	}
+	
+	void createBySecret(Resource<Secret> resource, Secret secret) {
+		var resourceAdapter = new ResourceAdapter<Secret>(resource);
+		resourceAdapter.create(secret);
+	}
+
+	UpdateControl<ElasticUserCustomResource> buildExceptionUpdateControl(ElasticUserCustomResource resource, Exception e) {
+		return ElasticUserUpdateControlBuilder
+				.fromResource(resource)
+				.withStatus(CustomResourceStatus.ERROR)
+				.withMessage(e.getMessage())
+				.withReschedule(OperatorConfig.RECONCILER_RETRY_SECONDS_ON_ERROR)
+				.build();
+	}
+}
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSpec.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSpec.java
new file mode 100644
index 0000000000000000000000000000000000000000..47b1ba6b0017c1ed5d6ccb458769a703b11d136c
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserSpec.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.operator.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Builder
+@JsonIgnoreProperties(ignoreUnknown = true)
+class ElasticUserSpec {
+
+}
diff --git a/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserUpdateControlBuilder.java b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserUpdateControlBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..88fa010555eb51075f39c1c67fec470f26fef8ca
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/main/java/de/ozgcloud/operator/user/ElasticUserUpdateControlBuilder.java
@@ -0,0 +1,63 @@
+package de.ozgcloud.operator.user;
+
+import java.time.Duration;
+import java.util.Optional;
+
+import de.ozgcloud.operator.CustomResourceStatus;
+import de.ozgcloud.operator.ElasticCustomResourceStatus;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+
+class ElasticUserUpdateControlBuilder {
+
+	private ElasticUserCustomResource resource;
+
+	private CustomResourceStatus status;
+	private Optional<String> message = Optional.empty();
+
+	private boolean reschedule = false;
+	private Duration scheduleDuration;
+
+	public ElasticUserUpdateControlBuilder(ElasticUserCustomResource resource) {
+		this.resource = resource;
+	}
+
+	public static ElasticUserUpdateControlBuilder fromResource(ElasticUserCustomResource resource) {
+		return new ElasticUserUpdateControlBuilder(resource);
+	}
+
+	public ElasticUserUpdateControlBuilder withStatus(CustomResourceStatus status) {
+		this.status = status;
+		return this;
+	}
+
+	public ElasticUserUpdateControlBuilder withMessage(String message) {
+		this.message = Optional.ofNullable(message);
+		return this;
+	}
+
+	public ElasticUserUpdateControlBuilder withReschedule(Duration duration) {
+		this.reschedule = true;
+		this.scheduleDuration = duration;
+		return this;
+	}
+
+	public UpdateControl<ElasticUserCustomResource> build() {
+		resource.setStatus(buildElasticCustomResourceStatus());
+
+		return buildUpdateControl();
+	}
+
+	private ElasticCustomResourceStatus buildElasticCustomResourceStatus() {
+		var userStatus = ElasticCustomResourceStatus.builder().status(status);
+		message.ifPresent(userStatus::message);
+
+		return userStatus.build();
+	}
+
+	private UpdateControl<ElasticUserCustomResource> buildUpdateControl() {
+		if (reschedule) {
+			return UpdateControl.updateStatus(resource).rescheduleAfter(scheduleDuration);
+		}
+		return UpdateControl.updateStatus(resource);
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcbbb653398c6a416e066204c267936aa245f007
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/KubernetesServiceTest.java
@@ -0,0 +1,109 @@
+package de.ozgcloud.operator.common.kubernetes;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.net.HttpURLConnection;
+
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import de.ozgcloud.operator.user.ObjectMetaTestFactory;
+import io.fabric8.kubernetes.api.model.Namespace;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.extension.ResourceAdapter;
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+
+class KubernetesServiceTest {
+
+	@Rule
+	private KubernetesServer server;
+	private KubernetesClient client;
+	private KubernetesService service;
+
+	@BeforeEach
+	void init() {
+		server = new KubernetesServer(true, true);
+		server.before();
+		client = server.getClient();
+		service = new KubernetesService(client);
+	}
+
+	@DisplayName("Exist namespace")
+	@Nested
+	class TestExistNamespace {
+
+		private final Namespace namespace = NamespaceTestFactory.create();
+		
+		@Test
+		public void shouldReturnTrueIfExistsWithCrud() {
+			var namespaceResource = client.namespaces().withName(ObjectMetaTestFactory.NAMESPACE);
+			var adapter = new ResourceAdapter<>(namespaceResource);
+			adapter.create(namespace);
+			
+			var exists = service.existNamespace(ObjectMetaTestFactory.NAMESPACE);
+
+			assertThat(exists).isTrue();
+		}
+
+		@Test
+		public void shouldReturnTrueIfExists() {
+			server.expect().get().withPath("/api/v1/namespaces/" + ObjectMetaTestFactory.NAMESPACE)
+					.andReturn(HttpURLConnection.HTTP_OK, namespace)
+					.once();
+
+			var exists = service.existNamespace(ObjectMetaTestFactory.NAMESPACE);
+
+			assertThat(exists).isTrue();
+		}
+
+		@Test
+		public void shouldReturnFalseIfMissing() {
+			var exists = service.existNamespace(ObjectMetaTestFactory.NAMESPACE);
+
+			assertThat(exists).isFalse();
+		}
+	}
+
+	@DisplayName("Get secret")
+	@Nested
+	class TestGetSecret {
+		
+		private final Secret secret = SecretTestFactory.create(); 
+
+		@Test
+		void shouldReturnExistingResourceIfExists() {
+			server.expect().get().withPath("/api/v1/namespaces/" + ObjectMetaTestFactory.NAMESPACE + "/secrets/" + SecretTestFactory.NAME)
+					.andReturn(HttpURLConnection.HTTP_OK, secret)
+					.once();
+
+			var secret = getSecret();
+
+			assertThat(secret).isNotNull();
+		}
+
+		@Test
+		void shouldReturnNullNOTExists() {
+			var secret = getSecret();
+
+			assertThat(secret).isNull();
+		}
+		
+		private Secret getSecret() {
+			return service.getSecretResource(ObjectMetaTestFactory.NAMESPACE, SecretTestFactory.NAME).get();
+		}
+	}
+	
+	//PoC
+	@Nested
+	class TestDoInPod {
+		
+		@Test
+		void doSomething() {
+			var pod = service.doInPod("test", "pod");
+		}
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/NamespaceTestFactory.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/NamespaceTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c1e6760d5441a75a9d8ea4bd16db7a37ea8d3ee
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/NamespaceTestFactory.java
@@ -0,0 +1,16 @@
+package de.ozgcloud.operator.common.kubernetes;
+
+import de.ozgcloud.operator.user.ObjectMetaTestFactory;
+import io.fabric8.kubernetes.api.model.Namespace;
+import io.fabric8.kubernetes.api.model.NamespaceBuilder;
+
+public class NamespaceTestFactory {
+
+	public static final Namespace create() {
+		return createBuilder().build();
+	}
+	
+	public static NamespaceBuilder createBuilder() {
+		return new NamespaceBuilder().withNewMetadata().withName(ObjectMetaTestFactory.NAMESPACE).endMetadata();
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/SecretTestFactory.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/SecretTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..debcddfcac36c3392f2e2808d35b5e613a8c7f74
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/common/kubernetes/SecretTestFactory.java
@@ -0,0 +1,21 @@
+package de.ozgcloud.operator.common.kubernetes;
+
+import de.ozgcloud.operator.user.ObjectMetaTestFactory;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.SecretBuilder;
+
+public class SecretTestFactory {
+	
+	final static String NAME = "secretName";
+
+	public static final Secret create() {
+		return createBuilder().build();
+	}
+	
+	public static final SecretBuilder createBuilder() {
+		var builder = new SecretBuilder();
+		builder.withNewMetadata().withName(NAME).withNamespace(ObjectMetaTestFactory.NAMESPACE).endMetadata().build();
+	
+		return builder;
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticCustomResourceStatusTestFactory.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticCustomResourceStatusTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..36fd6fdd20b507533a0e848e5f0900a4ffee0dd6
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticCustomResourceStatusTestFactory.java
@@ -0,0 +1,18 @@
+package de.ozgcloud.operator.user;
+
+import de.ozgcloud.operator.CustomResourceStatus;
+import de.ozgcloud.operator.ElasticCustomResourceStatus;
+
+public class ElasticCustomResourceStatusTestFactory {
+	
+	public final static CustomResourceStatus STATUS = CustomResourceStatus.OK;
+	
+	public static ElasticCustomResourceStatus create() {
+		return createBuilder().build();
+	}
+	
+	public static ElasticCustomResourceStatus.ElasticCustomResourceStatusBuilder createBuilder() {
+		return ElasticCustomResourceStatus.builder()
+				.status(STATUS);
+	}	
+}
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserCustomResourceTestFactory.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserCustomResourceTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..47599fb320b58a45f6dfc3c70b5a16d7accbb7bc
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserCustomResourceTestFactory.java
@@ -0,0 +1,11 @@
+package de.ozgcloud.operator.user;
+
+public class ElasticUserCustomResourceTestFactory {
+	
+	public static ElasticUserCustomResource create() {
+		var resource = new ElasticUserCustomResource();
+		resource.setStatus(ElasticCustomResourceStatusTestFactory.create());
+		resource.setMetadata(ObjectMetaTestFactory.create());
+		return resource;
+	}
+}
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerITCase.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9d9fb04fae958e01f307cd9ce04fcc6a740ae6d
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerITCase.java
@@ -0,0 +1,64 @@
+package de.ozgcloud.operator.user;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.net.HttpURLConnection;
+
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import io.fabric8.kubernetes.api.model.PodBuilder;
+import io.fabric8.kubernetes.api.model.PodList;
+import io.fabric8.kubernetes.api.model.PodListBuilder;
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient;
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+
+class ElasticUserReconcilerITCase {
+
+	@Rule
+	private final KubernetesServer server = new KubernetesServer();
+	private NamespacedKubernetesClient client;
+
+	@BeforeEach
+	void init() {
+		server.before();
+		client = server.getClient();
+	}
+
+	@DisplayName("Reconcile")
+	@Nested
+	class TestReconcile {
+
+		private final PodList podList = new PodListBuilder().withItems(
+				new PodBuilder().withNewMetadata().withName("pod1").endMetadata()
+						.build(),
+				new PodBuilder().withNewMetadata().withName("pod2").endMetadata()
+						.build())
+				.build();
+
+		@Test
+		public void shouldGetMockedPods() {
+			server.expect().get().withPath("/api/v1/pods").andReturn(HttpURLConnection.HTTP_OK, podList).once();
+
+			var podList = client.pods().inAnyNamespace().list();
+
+			assertThat(podList).isNotNull();
+			assertThat(podList.getItems()).hasSize(2);
+		}
+
+		@Test
+		public void shouldGetMockedPodsInNamespace() {
+			var namespace = "default";
+			server.expect().get().withPath("/api/v1/namespaces/" + namespace + "/pods")
+					.andReturn(HttpURLConnection.HTTP_OK, new PodListBuilder().build())
+					.once();
+
+			var podList = client.pods().inNamespace(namespace).list();
+
+			assertThat(podList.getItems()).isEmpty();
+		}
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerTest.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..20915e53c9a5bea0fe02a5c6b020c1477f743889
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserReconcilerTest.java
@@ -0,0 +1,48 @@
+package de.ozgcloud.operator.user;
+
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.operator.common.kubernetes.KubernetesService;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import lombok.SneakyThrows;
+
+class ElasticUserReconcilerTest {
+	
+	@Spy
+	@InjectMocks
+	private ElasticUserReconciler reconciler;
+	@Mock
+	private ElasticUserService service;
+	@Mock
+	private KubernetesService kubernetesService;
+
+	@DisplayName("Reconcile")
+	@Nested
+	class TestReconcile {
+		
+		@Mock
+		private Context<ElasticUserCustomResource> context;
+		
+		private final ElasticUserCustomResource resource = ElasticUserCustomResourceTestFactory.create();
+		
+		@Test
+		void shouldCreateSecret() {
+			reconcile();
+			
+			verify(service).checkSecret(resource, context);
+		}
+		
+		@SneakyThrows
+		private UpdateControl<ElasticUserCustomResource> reconcile() {
+			return reconciler.reconcile(resource, context);
+		}
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserSecretBuilderTest.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserSecretBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7795ab6468acacbc153975b61f59e9bd2777ef0a
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserSecretBuilderTest.java
@@ -0,0 +1,76 @@
+package de.ozgcloud.operator.user;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+class ElasticUserSecretBuilderTest {
+
+	private final ElasticUserSecretBuilder builder = new ElasticUserSecretBuilder();
+	
+	@DisplayName("Build")
+	@Nested
+	class TestBuild {
+		
+		private ElasticUserCustomResource resource = ElasticUserCustomResourceTestFactory.create();
+		private final String secretName = "SecretName";
+			
+		@Test
+		void shouldContainType() {
+			var secret = builder.build(resource, secretName);
+			
+			assertThat(secret.getType()).isEqualTo(ElasticUserSecretBuilder.SECRET_TYPE);
+		}
+		
+		
+		@DisplayName("metadata")
+		@Nested
+		class TestMetadata {
+			
+			@Test
+			void shouldContainName() {
+				var secret = builder.build(resource, secretName);
+				
+				assertThat(secret.getMetadata().getName()).isEqualTo(ElasticUserSecretBuilder.SECRET_TYPE);
+			}
+			
+			@Test
+			void shouldContainNamespace() {
+				var secret = builder.build(resource, secretName);
+				
+				assertThat(secret.getMetadata().getNamespace()).isEqualTo(ObjectMetaTestFactory.NAMESPACE);
+			}
+		}
+		
+		@Test
+		void shouldContainAddress() {
+			var secret = builder.build(resource, secretName);
+			
+			assertThat(secret.getStringData()).containsEntry(ElasticUserSecretBuilder.SECRET_ADDRESS_FIELD, ElasticUserSecretBuilder.SECRET_ADDRESS_VALUE);
+		}
+		
+		@Test
+		void shouldContainIndex() {
+			var secret = builder.build(resource, secretName);
+			
+			assertThat(secret.getStringData()).containsEntry(ElasticUserSecretBuilder.SECRET_INDEX_FIELD, ObjectMetaTestFactory.NAMESPACE);
+		}
+		
+		@Test
+		void shouldContainPassword() {
+			var secret = builder.build(resource, secretName);
+			
+			assertThat(secret.getStringData()).containsKey(ElasticUserSecretBuilder.SECRET_PASSWORD_FIELD);
+			assertThat(secret.getStringData().get(ElasticUserSecretBuilder.SECRET_PASSWORD_FIELD)).isNotNull();
+		}
+		
+		@Test
+		void shouldContainUsername() {
+			var secret = builder.build(resource, secretName);
+			
+			assertThat(secret.getStringData()).containsEntry(ElasticUserSecretBuilder.SECRET_USERNAME_FIELD, ObjectMetaTestFactory.NAMESPACE);
+		}
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserServiceTest.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..828d8b58c6120081b5ba341fc1496de60536c9a4
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ElasticUserServiceTest.java
@@ -0,0 +1,160 @@
+package de.ozgcloud.operator.user;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.operator.common.kubernetes.KubernetesService;
+import de.ozgcloud.operator.common.kubernetes.SecretTestFactory;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import io.fabric8.kubernetes.client.extension.ResourceAdapter;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+
+class ElasticUserServiceTest {
+	
+	@Spy
+	@InjectMocks
+	private ElasticUserService service;
+	@Mock
+	private ElasticUserSecretBuilder secretBuilder;
+	@Mock
+	private KubernetesService kubernetesService;
+
+	@DisplayName("Check secret")
+	@Nested
+	class TestCheckSecret {
+		
+		@Mock
+		private Context<ElasticUserCustomResource> context;
+		
+		private final ElasticUserCustomResource resource = ElasticUserCustomResourceTestFactory.create(); 
+		
+		@Test
+		void shouldGetSecret() {
+			service.checkSecret(resource, context);
+			
+			verify(kubernetesService).getSecretResource(ObjectMetaTestFactory.NAMESPACE, ElasticUserService.ELASTIC_USER_SECRET_NAME);
+		}
+		
+		@DisplayName("on missing secret")
+		@Nested
+		class TestOnMissingSecret {
+			
+			@Mock
+			private ResourceAdapter<Secret> resourceAdapter;
+			@Mock
+			private Resource<Secret> secretResource;
+			
+			private final Secret secret = SecretTestFactory.create();
+			
+			@BeforeEach
+			void mockResourceAdapter() {
+				when(kubernetesService.getSecretResource(any(), any())).thenReturn(secretResource);
+				when(secretResource.get()).thenReturn(null);
+				
+				doReturn(resourceAdapter).when(service).createAdapter(any());
+			}
+			
+			@Test
+			void shouldBuildSecret() {
+				service.checkSecret(resource, context);
+				
+				verify(secretBuilder).build(resource, ElasticUserService.ELASTIC_USER_SECRET_NAME);
+			}
+			
+			@Test
+			void shouldCreateSecret() {
+				when(secretBuilder.build(any(), any())).thenReturn(secret);
+				
+				service.checkSecret(resource, context);
+				
+				verify(resourceAdapter).create(secret);
+			}
+			
+			@DisplayName("update control")
+			@Nested
+			class TestUpdateControl {
+				
+				@Test
+				void shouldNotBeUpdateable() {
+					var updateControl = service.checkSecret(resource, context);
+					
+					assertThat(updateControl.isUpdateResourceAndStatus()).isFalse();
+				}
+				
+				@Test
+				void shouldContainResource() {
+					var updateControl = service.checkSecret(resource, context);
+					
+					assertThat(updateControl.getResource()).isEqualTo(resource);
+				}
+			}
+		}
+		
+		@DisplayName("On Exception")
+		@Nested
+		class TestOnException {
+			
+			private final Exception ex = new RuntimeException();
+			
+			@Test
+			void shouldBuildExceptionUpdateControlOnException() {
+				doThrow(ex).when(kubernetesService).getSecretResource(any(), any());
+				
+				service.checkSecret(resource, context);
+				
+				verify(service).buildExceptionUpdateControl(resource, ex);
+			}
+		}
+		
+		@DisplayName("build exception update control")
+		@Nested
+		class TestBuildExceptionUpdateControl {
+			
+			private final ElasticUserCustomResource resource = ElasticUserCustomResourceTestFactory.create(); 
+			private final Exception exception = new RuntimeException();
+			
+			@Test
+			void shouldContainResource() {
+				var updateControl = service.buildExceptionUpdateControl(resource, exception);
+				
+				assertThat(updateControl.getResource()).isEqualTo(resource);
+			}
+			
+			@Disabled("FIXME")
+			@Test
+			void shouldContainUpdateStatus() {
+				var updateControl = service.buildExceptionUpdateControl(resource, exception);
+				
+				assertThat(updateControl.isUpdateResource()).isFalse();
+				assertThat(updateControl.isPatchStatus()).isFalse();
+				assertThat(updateControl.isNoUpdate()).isFalse();
+			}
+			
+			@Test
+			void shouldContainReschedule() {
+				var updateControl = service.buildExceptionUpdateControl(resource, exception);
+				
+				assertThat(updateControl.getScheduleDelay()).hasValue(60000L);
+			}
+			
+			@Disabled("FIXME")
+			@Test
+			void shouldContainMessage() {
+				var updateControl = service.buildExceptionUpdateControl(resource, exception);
+				
+				//TBD?
+			}
+		}
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..817ff947b80cd762ed1d2faa9274518375777c77
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/java/de/ozgcloud/operator/user/ObjectMetaTestFactory.java
@@ -0,0 +1,15 @@
+package de.ozgcloud.operator.user;
+
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+
+public class ObjectMetaTestFactory {
+	
+	public static final String NAMESPACE ="TestNamespace";
+
+	public static ObjectMeta create() {
+		var objectMeta = new ObjectMeta();
+		objectMeta.setNamespace(NAMESPACE);
+		
+		return objectMeta;
+	}
+}
diff --git a/ozgcloud-elastic-operator/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/ozgcloud-elastic-operator/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000000000000000000000000000000000..79b126e6cdb86bec1f4f08c205de8961bde1934a
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
diff --git a/ozgcloud-elastic-operator/src/test/resources/junit-platform.properties b/ozgcloud-elastic-operator/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b059a65dc46792ea5494de02f888ab2ad08cd420
--- /dev/null
+++ b/ozgcloud-elastic-operator/src/test/resources/junit-platform.properties
@@ -0,0 +1 @@
+junit.jupiter.extensions.autodetection.enabled=true
\ No newline at end of file
diff --git a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/OzgCloudOperatorApplication.java b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/KeycloakOperatorApplication.java
similarity index 91%
rename from ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/OzgCloudOperatorApplication.java
rename to ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/KeycloakOperatorApplication.java
index 894e32da2cc92f48abb1edd810ba1e4855e469d3..27c3b688cde8c4fcdb5cfe23c058ffc9c2a5f192 100644
--- a/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/OzgCloudOperatorApplication.java
+++ b/ozgcloud-keycloak-operator/src/main/java/de/ozgcloud/operator/KeycloakOperatorApplication.java
@@ -27,9 +27,9 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
-public class OzgCloudOperatorApplication {
+public class KeycloakOperatorApplication {
 
 	public static void main(String[] args) {
-		SpringApplication.run(OzgCloudOperatorApplication.class, args);
+		SpringApplication.run(KeycloakOperatorApplication.class, args);
 	}
 }
diff --git a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/OzgOperatorApplicationTests.java b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/KeycloakOperatorApplicationTest.java
similarity index 96%
rename from ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/OzgOperatorApplicationTests.java
rename to ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/KeycloakOperatorApplicationTest.java
index c1f44350b15d1699808938451c32e7ae06a8af6a..52a4ee18784f2e3cd66467e8323b4fbe66ac3fe3 100644
--- a/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/OzgOperatorApplicationTests.java
+++ b/ozgcloud-keycloak-operator/src/test/java/de/ozgcloud/operator/KeycloakOperatorApplicationTest.java
@@ -27,7 +27,7 @@ import org.junit.jupiter.api.Test;
 
 //@SpringBootTest
 //@EnableMockOperator
-class OzgOperatorApplicationTests {
+class KeycloakOperatorApplicationTest {
 
 	@Test
 	void contextLoads() {
diff --git a/pom.xml b/pom.xml
index ce13f5a242e02dba43c370aea6e8c00fa1a6af28..dfe0be294b0e2eb108f0f775e6fd432b13daaeae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
 
 	<modules>
 		<module>ozgcloud-keycloak-operator</module>
+		<module>ozgcloud-elastic-operator</module>
 	</modules>
 
 	<properties>