diff --git a/scripts/start-vault.sh b/scripts/start-vault.sh new file mode 100755 index 00000000..dacb9aa5 --- /dev/null +++ b/scripts/start-vault.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +scriptdir="$(dirname "$0")" +cd "$scriptdir" + +PID_PATH_NAME="../airavata-mft/vault/vault-pid" +LOG_FILE="../airavata-mft/vault/vault.log" +VAULT_PATH_NAME="../airavata-mft/vault/vault" + +URL="" +ZIPFILE="" + +if [[ $OSTYPE == *"darwin"* ]]; +then + URL="https://releases.hashicorp.com/vault/1.14.1/vault_1.14.1_darwin_amd64.zip" + ZIPFILE="vault_1.14.1_darwin_amd64.zip" +elif [[ $OSTYPE == *"linux"* ]]; +then + URL="https://releases.hashicorp.com/vault/1.14.1/vault_1.14.1_linux_amd64.zip" + ZIPFILE="vault_1.14.1_linux_amd64.zip" +else + echo "As of now, airavata-mft only supports linux and mac" + exit 0 +fi + +if [ ! -f $PID_PATH_NAME ]; +then + mkdir -p ../airavata-mft/vault/keys +elif pgrep -x "vault" > /dev/null +then + # This is the condition where vault-pid file exists and + # vault is actually running + # Then this block will be executed + + # Reference: https://askubuntu.com/questions/157779/how-to-determine-whether-a-process-is-running-or-not-and-make-use-it-to-make-a-c + echo "Vault is already running ..." + exit 0 +fi + +# if vault-pid file exists or not but the vault executable itself does not exist +# then the following code will be executed +if [ ! -f $VAULT_PATH_NAME ] +then + curl -O $URL + unzip -o $ZIPFILE -d ../airavata-mft/vault + rm $ZIPFILE +fi + +# if the control structure reaches here, we have the vault executable ready to run +nohup ../airavata-mft/vault/vault server -config=./vault-config.hcl > $LOG_FILE 2>&1 & +echo $! > $PID_PATH_NAME # $! contains the pid of the recently started background process +echo "Vault started" + + +# Reference: +# https://stackoverflow.com/a/3232433 + + +#while True; do +# if [ -f $LOG_FILE ]; then +# lineCount=$(wc -l < $LOG_FILE | tr -d ' ' | tr -d '\n') +# lineCount="$(echo -e "${lineCount}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" +# if [[ $lineCount -gt 4 ]]; then +# echo "Log file is being updated"; +# break; +# fi +# fi +#done +# +#while IFS=':' read -r Key Value; +#do +# Key="$(echo -e "${Key}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" +# Value="$(echo -e "${Value}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" +# if [ "$Key" == "Api Address" ]; then +# echo "cat $LOG_FILE" +# echo "export VAULT_ADDR='$Value'" +# fi +#done < $LOG_FILE + diff --git a/scripts/stop-vault.sh b/scripts/stop-vault.sh new file mode 100755 index 00000000..9744e76e --- /dev/null +++ b/scripts/stop-vault.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +scriptdir="$(dirname "$0")" +cd "$scriptdir" + +PID_PATH_NAME="../airavata-mft/vault/vault-pid" +LOG_PATH_NAME="../airavata-mft/vault/vault.log" +NEW_PATH_NAME="../airavata-mft/vault/backup.log" + +if [ -f $PID_PATH_NAME ]; then + PID=$(cat $PID_PATH_NAME); + kill $PID; + echo "Vault stopped" + rm -rf $PID_PATH_NAME + mv $LOG_PATH_NAME $NEW_PATH_NAME +fi \ No newline at end of file diff --git a/scripts/vault-config.hcl b/scripts/vault-config.hcl new file mode 100644 index 00000000..d6cd889e --- /dev/null +++ b/scripts/vault-config.hcl @@ -0,0 +1,14 @@ +storage "file" { + path = "../airavata-mft/vault/vault-data" +} + +listener "tcp" { + address = "127.0.0.1:8200" + tls_disable = "true" +} + +disable_mlock = true + +api_addr = "http://127.0.0.1:8200" +cluster_addr = "http://127.0.0.1:8201" +ui = true diff --git a/services/secret-service/pom.xml b/services/secret-service/pom.xml index 9e772a57..b710af2a 100644 --- a/services/secret-service/pom.xml +++ b/services/secret-service/pom.xml @@ -35,6 +35,13 @@ client server + + + com.bettercloud + vault-java-driver + 5.1.0 + + mft-secret-service diff --git a/services/secret-service/server/pom.xml b/services/secret-service/server/pom.xml index f6dd4066..6ce49f51 100644 --- a/services/secret-service/server/pom.xml +++ b/services/secret-service/server/pom.xml @@ -74,6 +74,16 @@ dozer ${dozer} + + com.google.code.gson + gson + 2.10.1 + + + org.json + json + 20140107 + diff --git a/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/VaultSecretBackend.java b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/VaultSecretBackend.java new file mode 100644 index 00000000..ecf2c957 --- /dev/null +++ b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/VaultSecretBackend.java @@ -0,0 +1,868 @@ +package org.apache.airavata.mft.secret.server.backend.vault; + +import com.bettercloud.vault.Vault; +import com.bettercloud.vault.VaultConfig; +import com.bettercloud.vault.VaultException; +import com.bettercloud.vault.api.Seal; +import com.bettercloud.vault.api.mounts.*; +import com.bettercloud.vault.response.LogicalResponse; +import com.bettercloud.vault.response.MountResponse; +import com.bettercloud.vault.response.SealResponse; +import com.google.gson.Gson; +import org.apache.airavata.mft.credential.stubs.azure.*; +import org.apache.airavata.mft.credential.stubs.box.*; +import org.apache.airavata.mft.credential.stubs.dropbox.*; +import org.apache.airavata.mft.credential.stubs.ftp.*; +import org.apache.airavata.mft.credential.stubs.gcs.*; +import org.apache.airavata.mft.credential.stubs.http.*; +import org.apache.airavata.mft.credential.stubs.odata.*; +import org.apache.airavata.mft.credential.stubs.s3.*; +import org.apache.airavata.mft.credential.stubs.scp.*; +import org.apache.airavata.mft.credential.stubs.swift.*; +import org.apache.airavata.mft.secret.server.backend.SecretBackend; +import org.apache.airavata.mft.secret.server.backend.vault.entity.SCPSecretEntity; +import org.dozer.DozerBeanMapper; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component("VaultSecretBackend") +public class VaultSecretBackend implements SecretBackend { + private static final Logger logger = LoggerFactory.getLogger(VaultSecretBackend.class); + private static Vault vault; + + private VaultInitData vaultGlobalCreds = null; + + private static final Map pathMap = new HashMap<>(); + + private final String vaultCredsPath="./airavata-mft/vault/keys/unseal.keys"; + + private final String VAULT_ADDR = "http://127.0.0.1:8200"; + + + private final DozerBeanMapper mapper = new DozerBeanMapper(); + + // Reference: https://stackoverflow.com/questions/1053467/how-do-i-save-a-string-to-a-text-file-using-java + + private VaultInitData setVaultInit(String body) { + VaultInitData vaultInitData = new VaultInitData(); + JSONObject field = new JSONObject(body); + JSONArray keysArray = field.getJSONArray("keys"); + JSONArray keysBase64Array = field.getJSONArray("keys_base64"); + String root_token = field.getString("root_token"); + + String[] keys = new String[keysArray.length()]; + for(int j=0; j mounts = response.getMounts(); + if (!mounts.containsKey("secret/")) { + mountPath(); + } + } catch (VaultException e) { + logger.error("Error while mounting the path", e); + throw new RuntimeException(e); + } + populatePathsToMap(); + + + + logger.info("Initializing the Vault Completed"); + } + + /** + * + */ + @Override + public void destroy() { + + } + + /** + * @param request + * @return + */ + @Override + public SCPSecret createSCPSecret(SCPSecretCreateRequest request) { + logger.info("Creating SCP secret"); + SCPSecretEntity entity = new SCPSecretEntity(); + Gson gson = new Gson(); + + + // Generate UUID + String uuid = UUID.randomUUID().toString(); + entity.setSecretId(uuid); + entity.setPrivateKey(request.getPrivateKey()); + entity.setPublicKey(request.getPublicKey()); + entity.setPassphrase(request.getPassphrase()); + entity.setUser(request.getUser()); + + Map readMap; + + try { + readMap = vault.withRetries(5, 1000).logical().read(pathMap.get("scp")).getData(); + } catch (VaultException e) { + logger.error("Error while reading the secrets in the deleteSecrets() method", e); + throw new RuntimeException(e); + } + + + + // Map secrets = new HashMap<>(); + // SecretId is chosen as the key because SCPSecretGetRequest only has getters for SecretId + readMap.put(entity.getSecretId(), gson.toJson(entity)); + + // Copy it to new map with as + Map secrets = new HashMap<>(readMap); + + try { + vault.withRetries(5, 1000).logical().write(pathMap.get("scp"), secrets); + } catch (VaultException e) { + logger.error("Error while writing secrets to secret/scp", e); + + e.printStackTrace(); + throw new RuntimeException(e); + } + + logger.info("Completed writing created SCP secret into the vault"); + + return mapper.map(entity, SCPSecret.newBuilder().getClass()).build(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getSCPSecret(SCPSecretGetRequest request) throws Exception { + logger.info("Fetching the required SCP secret from the vault"); + String secretId = request.getSecretId(); + + String readString; + Gson gson = new Gson(); + + + Map readMap; + + try { + readMap = vault.withRetries(5, 1000).logical().read(pathMap.get("scp")).getData(); + } catch (VaultException e) { + logger.error("Error while reading the secrets in the deleteSecrets() method", e); + throw new RuntimeException(e); + } + + readString = readMap.get(request.getSecretId()); + + if (readString == null) { + logger.info("Unable to fetch the required SCP secret from the vault"); + return Optional.empty(); + } + + SCPSecretEntity entity = gson.fromJson(readString, SCPSecretEntity.class); + SCPSecret scpSecret = mapper.map(entity, SCPSecret.newBuilder().getClass()).build(); + + logger.info("Returning the required SCP secret from the vault"); + + return Optional.of(scpSecret); + } + + + + /** + * @param request + * @return + */ + @Override + public boolean updateSCPSecret(SCPSecretUpdateRequest request) { + logger.info("Updating the required SCP secret from the vault"); + // https://protobuf.dev/reference/java/java-generated/ + // Not checking for null for protocol getters based on the above reference + + if (request.getSecretId().equals("")) { + // if secretId is null or empty + logger.warn("Secret ID cannot be null or empty"); + return false; + } + + Gson gson = new Gson(); + + Map readMap; + + try { + readMap = vault.withRetries(5, 1000).logical().read(pathMap.get("scp")).getData(); + } catch (VaultException e) { + logger.error("Error while reading the secrets in the deleteSecrets() method", e); + return false; + } + + String value = readMap.get(request.getSecretId()); + + if (value == null) { + logger.info("Secret ID does not exist in the vault"); + return false; + } + + SCPSecretEntity existingEntity = null; + + // populate existing entity + int flag = 0; + for (String key: readMap.keySet()) { + if (key.equals(request.getSecretId())) { + flag = 1; + // Now populate the existing values to entity + existingEntity = gson.fromJson(readMap.get(key), SCPSecretEntity.class); + break; + } + } + + if (flag == 0) { + // if the sent secret id did not match with existing secret ids + // return false + logger.warn("Sent Secret ID did not match with existing secret IDs"); + return false; + } + + + if (!request.getUser().equals("")) { + existingEntity.setUser(request.getUser()); + } + + if (!request.getPassphrase().equals("")) { + existingEntity.setPassphrase(request.getPassphrase()); + } + + if (!request.getPrivateKey().equals("")) { + existingEntity.setPrivateKey(request.getPrivateKey()); + } + + if (!request.getPublicKey().equals("")) { + existingEntity.setPublicKey(request.getPublicKey()); + } + + // Modify the required kv pair in the read map + readMap.put(request.getSecretId(), gson.toJson(existingEntity)); + + + // Copy it to new map with as + Map secrets = new HashMap<>(readMap); + + // write it again to vault + try { + vault.logical().write(pathMap.get("scp"), secrets); + } catch (VaultException e) { + logger.error("Error while writing secrets to secret/scp", e); + throw new RuntimeException(e); + } + + logger.info("Updated the required secret successfully"); + return true; + } + + /** + * @param request + * @return + */ + @Override + public boolean deleteSCPSecret(SCPSecretDeleteRequest request) { + logger.info("Deleting the required SCP secret from the vault"); + Map readMap; + + try { + readMap = vault.withRetries(5, 1000).logical().read(pathMap.get("scp")).getData(); + } catch (VaultException e) { + logger.error("Error while reading the secrets in the deleteSecrets() method", e); + return false; + } + + if (readMap == null || readMap.keySet().size() <= 1) { + try { + vault.logical().delete(pathMap.get("scp")); + logger.info("Deleted the required SCP secret from the vault"); + return true; + } catch (VaultException e) { + logger.error("Error while deleting the secrets in the deleteSecrets() method", e); + return false; + } + } + + readMap.remove(request.getSecretId()); + + Map secrets = new HashMap<>(readMap); + + try { + vault.logical().write(pathMap.get("scp"), secrets); + } catch (VaultException e) { + logger.error("Error while writing secrets to secret/scp", e); + return false; + } + + logger.info("Deleted the required SCP secret from the vault"); + return true; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getS3Secret(S3SecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public S3Secret createS3Secret(S3SecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateS3Secret(S3SecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteS3Secret(S3SecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getBoxSecret(BoxSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public BoxSecret createBoxSecret(BoxSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateBoxSecret(BoxSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteBoxSecret(BoxSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getAzureSecret(AzureSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public AzureSecret createAzureSecret(AzureSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateAzureSecret(AzureSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteAzureSecret(AzureSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getGCSSecret(GCSSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public GCSSecret createGCSSecret(GCSSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateGCSSecret(GCSSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteGCSSecret(GCSSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getDropboxSecret(DropboxSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public DropboxSecret createDropboxSecret(DropboxSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateDropboxSecret(DropboxSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteDropboxSecret(DropboxSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getFTPSecret(FTPSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public FTPSecret createFTPSecret(FTPSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateFTPSecret(FTPSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteFTPSecret(FTPSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getSwiftSecret(SwiftSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public SwiftSecret createSwiftSecret(SwiftSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateSwiftSecret(SwiftSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteSwiftSecret(SwiftSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getODataSecret(ODataSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public ODataSecret createODataSecret(ODataSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateODataSecret(ODataSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteODataSecret(ODataSecretDeleteRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public Optional getHttpSecret(HTTPSecretGetRequest request) throws Exception { + return Optional.empty(); + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public HTTPSecret createHttpSecret(HTTPSecretCreateRequest request) throws Exception { + return null; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean updateHttpSecret(HTTPSecretUpdateRequest request) throws Exception { + return false; + } + + /** + * @param request + * @return + * @throws Exception + */ + @Override + public boolean deleteHttpSecret(HTTPSecretDeleteRequest request) throws Exception { + return false; + } +} + +class VaultInitData { + private String[] keys; + private String[] keys_base64; + private String root_token; + + public String[] getKeys() { + return keys; + } + + public String[] getKeys_base64() { + return keys_base64; + } + + public String getRoot_token() { + return root_token; + } + + public void setKeys(String[] keys) { + this.keys = keys; + } + + public void setKeys_base64(String[] keys_base64) { + this.keys_base64 = keys_base64; + } + + public void setRoot_token(String root_token) { + this.root_token = root_token; + } +} diff --git a/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/entity/SCPSecretEntity.java b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/entity/SCPSecretEntity.java new file mode 100644 index 00000000..033977e5 --- /dev/null +++ b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/backend/vault/entity/SCPSecretEntity.java @@ -0,0 +1,50 @@ +package org.apache.airavata.mft.secret.server.backend.vault.entity; + + +public class SCPSecretEntity { + private String secretId; + private String privateKey; + private String publicKey; + private String passphrase; + private String user; + + public String getSecretId() { + return secretId; + } + + public void setSecretId(String secretId) { + this.secretId = secretId; + } + + public String getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + + public String getPublicKey() { + return publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public String getPassphrase() { + return passphrase; + } + + public void setPassphrase(String passphrase) { + this.passphrase = passphrase; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } +} diff --git a/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/handler/SCPServiceHandler.java b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/handler/SCPServiceHandler.java index e40e5112..9ecc475e 100644 --- a/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/handler/SCPServiceHandler.java +++ b/services/secret-service/server/src/main/java/org/apache/airavata/mft/secret/server/handler/SCPServiceHandler.java @@ -36,7 +36,7 @@ public class SCPServiceHandler extends SCPSecretServiceGrpc.SCPSecretServiceImpl private static final Logger logger = LoggerFactory.getLogger(SCPServiceHandler.class); @Autowired - @Qualifier("SQLSecretBackend") + @Qualifier("VaultSecretBackend") private SecretBackend backend; @Override diff --git a/services/secret-service/server/src/main/resources/applicationContext.xml b/services/secret-service/server/src/main/resources/applicationContext.xml index 3573f3f5..14199d1c 100644 --- a/services/secret-service/server/src/main/resources/applicationContext.xml +++ b/services/secret-service/server/src/main/resources/applicationContext.xml @@ -29,7 +29,7 @@ - - \ No newline at end of file + diff --git a/services/secret-service/server/src/main/resources/distribution/conf/applicationContext.xml b/services/secret-service/server/src/main/resources/distribution/conf/applicationContext.xml index 592ea62f..74bd27ae 100644 --- a/services/secret-service/server/src/main/resources/distribution/conf/applicationContext.xml +++ b/services/secret-service/server/src/main/resources/distribution/conf/applicationContext.xml @@ -29,7 +29,7 @@ - - \ No newline at end of file +