From 692f35a5695889a15f3b560173f93b57a9412d34 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Thu, 4 Jan 2024 10:46:14 +0100
Subject: [PATCH] OZG-4453 decode password from secret

---
 .../operator/ElasticsearchReconciler.java     | 15 ++++++--
 .../OzgCloudElasticsearchService.java         |  7 +---
 .../operator/ElasticsearchReconcilerTest.java | 38 ++++++++++++++++++-
 3 files changed, 49 insertions(+), 11 deletions(-)

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 4d7e387..268157f 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
@@ -1,5 +1,6 @@
 package de.ozgcloud.operator;
 
+import java.util.Base64;
 import java.util.logging.Level;
 
 import org.apache.commons.collections.MapUtils;
@@ -41,11 +42,19 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch
 		}
 	}
 	
-	private String getPassword(Secret secret) {
+	String getPassword(Secret secret) {
 		log.info("get password for elastic user...");
 		log.info(String.format("from secret string map: %s", secret.getStringData()));
 		log.info(String.format("from secret data map: %s", secret.getData()));
-		return MapUtils.getString(secret.getData(), OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD);
+		return decode(MapUtils.getString(secret.getData(), OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD));
+	}
+	
+	private String decode(String encodedPassword) {
+		try {
+			return new String(Base64.getDecoder().decode(encodedPassword));
+		} catch (Exception e) {
+			throw new RuntimeException("Could not decode password from secret.");
+		}
 	}
 	
 	UpdateControl<OzgCloudElasticsearchCustomResource> buildExceptionUpdateControl(OzgCloudElasticsearchCustomResource resource, Exception exception) {
@@ -66,7 +75,7 @@ public class ElasticsearchReconciler implements Reconciler<OzgCloudElasticsearch
 			service.deleteIndexIfExists(namespace);
 			return DeleteControl.defaultDelete();
 		} catch(Exception e) {
-			log.log(Level.INFO, String.format("Could not cleanup elasticsearch resource in namespace %s. \n %s", namespace, e));
+			log.log(Level.INFO, String.format("Could not cleanup elasticsearch resource in namespace %s. %n %s", namespace, e));
 			return DeleteControl.defaultDelete();
 		}
 	}
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 4ddb321..9962e01 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
@@ -55,7 +55,6 @@ public class OzgCloudElasticsearchService {
 		createAdapter(resource).create(secretHelper.buildCredentialSecret(namespace, properties.getSecretCredentialsName()));
 	}
 		
-//	curl -k -X PUT -u elastic:$ELASTICSEARCH_PASSWORD -H 'Content-Type: application/json' 'https://ozg-search-cluster-es-http:9200/'$ES_NS_USER
 	public void createIndexIfMissing(String name) throws Exception {
 		log.info("Check index...");
 		if(!remoteService.existsIndex(name)) {
@@ -64,8 +63,6 @@ public class OzgCloudElasticsearchService {
 		log.info("Check index successful.");
 	}
 	
-//	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"] } ] }'
 	public void createSecurityRoleIfMissing(String roleName) throws Exception {
 		log.info("Check security role...");
 		if(!remoteService.existsSecurityRole(roleName)) {
@@ -82,8 +79,6 @@ public class OzgCloudElasticsearchService {
 		return IndicesPrivilegesData.builder().names(roleName).privileges(IndicesPrivilege.ALL.getValue()).build();
 	}
 	
-//	 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'" ]}'
 	public void createSecurityUserIfMissing(String namespace, String password) throws Exception {
 		log.info("Check security user...");
 		if(!remoteService.existsSecurityUser(namespace)) {
@@ -147,6 +142,6 @@ public class OzgCloudElasticsearchService {
 	}
 	
 	ResourceAdapter<Secret> createAdapter(Resource<Secret> resource) {
-		return new ResourceAdapter<Secret>(resource);
+		return new ResourceAdapter<>(resource);
 	}
 }
\ No newline at end of file
diff --git a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java
index d75e012..16dc22c 100644
--- a/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java
+++ b/ozgcloud-elasticsearch-operator/src/test/java/de/ozgcloud/operator/ElasticsearchReconcilerTest.java
@@ -4,6 +4,9 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Base64;
+import java.util.Map;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -12,9 +15,12 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.operator.common.kubernetes.NamespaceTestFactory;
 import de.ozgcloud.operator.common.kubernetes.SecretTestFactory;
 import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.SecretBuilder;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
 import lombok.SneakyThrows;
@@ -36,7 +42,8 @@ class ElasticsearchReconcilerTest {
 		
 		private final OzgCloudElasticsearchCustomResource resource = ElasticsearchCustomResourceTestFactory.create();
 		
-		private final static String PASSWORD = "dummyPassword";
+		private final static String PASSWORD = new String(Base64.getEncoder().encode("dummyPassword".getBytes()));
+		private final static String DECODED_PASSWORD = new String(Base64.getDecoder().decode(PASSWORD));
 		private final Secret secret = SecretTestFactory.createBuilder().addToData(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD, PASSWORD).build();
 		
 		@DisplayName("process flow")
@@ -76,7 +83,7 @@ class ElasticsearchReconcilerTest {
 			void shouldCallCreateSecurityUserIfMissing() {
 				reconcile();
 				
-				verify(service).createSecurityUserIfMissing(NamespaceTestFactory.NAMESPACE, PASSWORD);
+				verify(service).createSecurityUserIfMissing(NamespaceTestFactory.NAMESPACE, DECODED_PASSWORD);
 			}
 			
 			@SneakyThrows
@@ -152,6 +159,33 @@ class ElasticsearchReconcilerTest {
 				return reconciler.buildExceptionUpdateControl(resource, exception);
 			}
 		}
+		
+		@DisplayName("get password")
+		@Nested
+		class TestGetPassword {
+			
+			private static final String SECRET_PASSWORD = LoremIpsum.getInstance().getWords(1);
+
+			@Test
+			void shouldReturnPasssowrd() {
+				var secret = buildSecret();
+
+				var password = reconciler.getPassword(secret);
+
+				assertThat(password).isEqualTo(SECRET_PASSWORD);
+			}
+
+			private Secret buildSecret() {
+				return new SecretBuilder()
+						.addToData(Map.of(OzgCloudElasticsearchSecretHelper.CREDENTIAL_SECRET_PASSWORD_FIELD,
+								encodeStringBase64(SECRET_PASSWORD)))
+						.build();
+			}
+
+			private String encodeStringBase64(String string) {
+				return Base64.getEncoder().encodeToString(string.getBytes());
+			}
+		}
 	}
 	
 	@DisplayName("Cleanup")
-- 
GitLab