You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by sn...@apache.org on 2015/05/23 02:29:30 UTC

incubator-ranger git commit: RANGER-504: Fixed KMS Client to handle multiple KMS instances in URL

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 0421271e2 -> 14ec7d526


RANGER-504: Fixed KMS Client to handle multiple KMS instances in URL

Signed-off-by: sneethiraj <sn...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/14ec7d52
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/14ec7d52
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/14ec7d52

Branch: refs/heads/master
Commit: 14ec7d526b344a597f81b31613416c383c94f467
Parents: 0421271
Author: Velmurugan Periasamy <ve...@apache.org>
Authored: Fri May 22 20:15:03 2015 -0400
Committer: sneethiraj <sn...@apache.org>
Committed: Fri May 22 20:24:41 2015 -0400

----------------------------------------------------------------------
 .../ranger/services/kms/client/KMSClient.java   | 306 +++++++++++------
 .../java/org/apache/ranger/biz/KmsKeyMgr.java   | 331 ++++++++++++++-----
 2 files changed, 457 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/14ec7d52/plugin-kms/src/main/java/org/apache/ranger/services/kms/client/KMSClient.java
----------------------------------------------------------------------
diff --git a/plugin-kms/src/main/java/org/apache/ranger/services/kms/client/KMSClient.java b/plugin-kms/src/main/java/org/apache/ranger/services/kms/client/KMSClient.java
index 60e9bd3..59fa634 100755
--- a/plugin-kms/src/main/java/org/apache/ranger/services/kms/client/KMSClient.java
+++ b/plugin-kms/src/main/java/org/apache/ranger/services/kms/client/KMSClient.java
@@ -19,17 +19,25 @@
 
 package org.apache.ranger.services.kms.client;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.ProviderUtils;
 import org.apache.log4j.Logger;
 import org.apache.ranger.plugin.client.BaseClient;
 import org.apache.ranger.plugin.client.HadoopException;
 import org.apache.ranger.services.kms.client.KMSClient;
 
+import com.google.common.base.Strings;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.sun.jersey.api.client.Client;
@@ -38,122 +46,209 @@ import com.sun.jersey.api.client.WebResource;
 
 public class KMSClient {
 
-	public static final Logger LOG = Logger.getLogger(KMSClient.class) ;
+	public static final Logger LOG = Logger.getLogger(KMSClient.class);
 
 	private static final String EXPECTED_MIME_TYPE = "application/json";
-	
-	private static final String KMS_LIST_API_ENDPOINT = "v1/keys/names?user.name=${userName}";			//GET
-	
-	private static final String errMessage =  " You can still save the repository and start creating "
-											  + "policies, but you would not be able to use autocomplete for "
-											  + "resource names. Check xa_portal.log for more info.";
-	
+
+	private static final String KMS_LIST_API_ENDPOINT = "v1/keys/names?user.name=${userName}"; // GET
+
+	private static final String errMessage = " You can still save the repository and start creating "
+			+ "policies, but you would not be able to use autocomplete for "
+			+ "resource names. Check xa_portal.log for more info.";
+
 	String provider;
 	String username;
 	String password;
 
-	public  KMSClient(String provider, String username, String password) {
-		provider = provider.replaceAll("kms://","");
-		provider = provider.replaceAll("http@","http://");		
+	public KMSClient(String provider, String username, String password) {
 		this.provider = provider;
-		this.username = username ;
+		this.username = username;
 		this.password = password;
-		
+
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("Kms Client is build with url [" + provider + "] user: [" + username + "]");
-		}		
+			LOG.debug("Kms Client is build with url [" + provider + "] user: ["
+					+ username + "]");
+		}
+	}
+
+	private String[] createProvider(String uri) throws IOException,
+			URISyntaxException {
+		URI providerUri = new URI(uri);
+		URL origUrl = new URL(extractKMSPath(providerUri).toString());
+		String authority = origUrl.getAuthority();
+		// check for ';' which delimits the backup hosts
+		if (Strings.isNullOrEmpty(authority)) {
+			throw new IOException("No valid authority in kms uri [" + origUrl
+					+ "]");
+		}
+		// Check if port is present in authority
+		// In the current scheme, all hosts have to run on the same port
+		int port = -1;
+		String hostsPart = authority;
+		if (authority.contains(":")) {
+			String[] t = authority.split(":");
+			try {
+				port = Integer.parseInt(t[1]);
+			} catch (Exception e) {
+				throw new IOException("Could not parse port in kms uri ["
+						+ origUrl + "]");
+			}
+			hostsPart = t[0];
+		}
+		return createProvider(providerUri, origUrl, port, hostsPart);
+	}
+
+	private static Path extractKMSPath(URI uri) throws MalformedURLException,
+			IOException {
+		return ProviderUtils.unnestUri(uri);
 	}
-	
-	public List<String> getKeyList(final String keyNameMatching, final List<String> existingKeyList) {
+
+	private String[] createProvider(URI providerUri, URL origUrl, int port,
+			String hostsPart) throws IOException {
+		String[] hosts = hostsPart.split(";");
+		String[] providers = new String[hosts.length];
+		if (hosts.length == 1) {
+			providers[0] = origUrl.toString();
+		} else {
+			for (int i = 0; i < hosts.length; i++) {
+				try {
+					String url = origUrl.getProtocol() + "://" + hosts[i] + ":"
+							+ port + origUrl.getPath();
+					providers[i] = new URI(url).toString();
+				} catch (URISyntaxException e) {
+					throw new IOException("Could not Prase KMS URL..", e);
+				}
+			}
+		}
+		return providers;
+	}
+
+	public List<String> getKeyList(final String keyNameMatching,
+			final List<String> existingKeyList) {
 		
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("Getting Kms Key list for keyNameMatching : " + keyNameMatching);
+		String providers[] = null;
+		try {
+			providers = createProvider(provider);
+		} catch (IOException | URISyntaxException e) {
+			return null;
 		}
 		final String errMsg = errMessage;
-		List<String> lret = new ArrayList<String>();				
-		String keyLists = KMS_LIST_API_ENDPOINT.replaceAll(Pattern.quote("${userName}"), username);
-		String uri = provider + (provider.endsWith("/") ? keyLists : ("/" + keyLists));		
-		Client client = null ;
-		ClientResponse response = null ;
-				
-		try {
-			client = Client.create() ;
-			
-			WebResource webResource = client.resource(uri);
-			
-			response = webResource.accept(EXPECTED_MIME_TYPE).get(ClientResponse.class);
-			
+		List<String> lret = null;
+		for (int i = 0; i < providers.length; i++) {
+			lret  = new ArrayList<String>();
 			if (LOG.isDebugEnabled()) {
-				LOG.debug("getKeyList():calling " + uri);
+				LOG.debug("Getting Kms Key list for keyNameMatching : "
+						+ keyNameMatching);
 			}
-			
-			if (response != null) {
+			String keyLists = KMS_LIST_API_ENDPOINT.replaceAll(
+					Pattern.quote("${userName}"), username);
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? keyLists : ("/" + keyLists));
+			Client client = null;
+			ClientResponse response = null;
+
+			try {
+				client = Client.create();
+
+				WebResource webResource = client.resource(uri);
+
+				response = webResource.accept(EXPECTED_MIME_TYPE).get(
+						ClientResponse.class);
+
 				if (LOG.isDebugEnabled()) {
-					LOG.debug("getKeyList():response.getStatus()= " + response.getStatus());	
+					LOG.debug("getKeyList():calling " + uri);
 				}
-				if (response.getStatus() == 200) {
-					String jsonString = response.getEntity(String.class);
-					Gson gson = new GsonBuilder().setPrettyPrinting().create();
-					@SuppressWarnings("unchecked")
-					List<String> keys = gson.fromJson(jsonString, List.class) ;					
-					if (keys != null) {
-						for ( String key : keys) {
-							if ( existingKeyList != null && existingKeyList.contains(key)) {
-						        	continue;
-						        }
-								if (keyNameMatching == null || keyNameMatching.isEmpty() || key.startsWith(keyNameMatching)) {
-										if (LOG.isDebugEnabled()) {
-											LOG.debug("getKeyList():Adding kmsKey " + key);
-										}
-										lret.add(key) ;
+				if (response != null) {
+					if (LOG.isDebugEnabled()) {
+						LOG.debug("getKeyList():response.getStatus()= "
+								+ response.getStatus());
+					}
+					if (response.getStatus() == 200) {
+						String jsonString = response.getEntity(String.class);
+						Gson gson = new GsonBuilder().setPrettyPrinting()
+								.create();
+						@SuppressWarnings("unchecked")
+						List<String> keys = gson.fromJson(jsonString,
+								List.class);
+						if (keys != null) {
+							for (String key : keys) {
+								if (existingKeyList != null
+										&& existingKeyList.contains(key)) {
+									continue;
+								}
+								if (keyNameMatching == null
+										|| keyNameMatching.isEmpty()
+										|| key.startsWith(keyNameMatching)) {
+									if (LOG.isDebugEnabled()) {
+										LOG.debug("getKeyList():Adding kmsKey "
+												+ key);
 									}
+									lret.add(key);
+								}
 							}
-						}							
-				 }else if (response.getStatus() == 401) {
-					 LOG.info("getKeyList():response.getStatus()= " + response.getStatus() + " for URL " + uri + ", so returning null list");
-					 return lret;
-				 }else if (response.getStatus() == 403) {
-					 LOG.info("getKeyList():response.getStatus()= " + response.getStatus() + " for URL " + uri + ", so returning null list");
-					 return lret;
-				 }else {
-					 LOG.info("getKeyList():response.getStatus()= " + response.getStatus() + " for URL " + uri + ", so returning null list");	
-					 String jsonString = response.getEntity(String.class);
-					 LOG.info(jsonString);
-					 lret = null;
+							return lret;
+						}						
+					} else if (response.getStatus() == 401) {
+						LOG.info("getKeyList():response.getStatus()= "
+								+ response.getStatus() + " for URL " + uri
+								+ ", so returning null list");
+						return lret;
+					} else if (response.getStatus() == 403) {
+						LOG.info("getKeyList():response.getStatus()= "
+								+ response.getStatus() + " for URL " + uri
+								+ ", so returning null list");
+						return lret;
+					} else {
+						LOG.info("getKeyList():response.getStatus()= "
+								+ response.getStatus() + " for URL " + uri
+								+ ", so returning null list");
+						String jsonString = response.getEntity(String.class);
+						LOG.info(jsonString);
+						lret = null;
+					}
+				} else {
+					String msgDesc = "Unable to get a valid response for "
+							+ "expected mime type : [" + EXPECTED_MIME_TYPE
+							+ "] URL : " + uri + " - got null response.";
+					LOG.error(msgDesc);
+					HadoopException hdpException = new HadoopException(msgDesc);
+					hdpException.generateResponseDataMap(false, msgDesc,
+							msgDesc + errMsg, null, null);
+					lret = null;
+					throw hdpException;
 				}
-			}else {
-				String msgDesc = "Unable to get a valid response for "
-						+ "expected mime type : [" + EXPECTED_MIME_TYPE
-						+ "] URL : " + uri + " - got null response.";
-				LOG.error(msgDesc);
-				HadoopException hdpException = new HadoopException(msgDesc);
-				hdpException.generateResponseDataMap(false, msgDesc, msgDesc + errMsg, null, null);
+			} catch (HadoopException he) {
+				lret = null;
+				throw he;
+			} catch (Throwable t) {
+				String msgDesc = "Exception while getting Kms Key List. URL : "
+						+ uri;
+				HadoopException hdpException = new HadoopException(msgDesc, t);
+				LOG.error(msgDesc, t);
+				hdpException.generateResponseDataMap(false,
+						BaseClient.getMessage(t), msgDesc + errMsg, null, null);
 				lret = null;
 				throw hdpException;
-			}
-		} catch (HadoopException he) {
-			lret = null;
-			throw he;
-		}catch (Throwable t) {
-			String msgDesc = "Exception while getting Kms Key List. URL : " + uri;
-			HadoopException hdpException = new HadoopException(msgDesc, t);
-			LOG.error(msgDesc, t);
-			hdpException.generateResponseDataMap(false, BaseClient.getMessage(t), msgDesc + errMsg, null, null);
-			lret = null;
-			throw hdpException;					
-		} finally {
-			if (response != null) {
-				response.close();
-			}
-			
-			if (client != null) {
-				client.destroy(); 
-			}				
+			} finally {
+				if (response != null) {
+					response.close();
+				}
+
+				if (client != null) {
+					client.destroy();
+				}
+				
+				if(lret == null){
+					if (i != providers.length - 1)
+						continue;					
+				}
+			}			
 		}
-		return lret ;			
+		return lret;
 	}
-		
-	public static HashMap<String, Object> testConnection(String serviceName, Map<String, String> configs) {
+
+	public static HashMap<String, Object> testConnection(String serviceName,
+			Map<String, String> configs) {
 
 		List<String> strList = new ArrayList<String>();
 		String errMsg = errMessage;
@@ -170,7 +265,7 @@ public class KMSClient {
 			BaseClient.generateResponseDataMap(connectivityStatus, successMsg,
 					successMsg, null, null, responseData);
 		} else {
-			String failureMsg = "Unable to retrieve any Kms Key using given parameters.";
+			String failureMsg = "Unable to retrieve any Kms Key using given URL.";
 			BaseClient.generateResponseDataMap(connectivityStatus, failureMsg,
 					failureMsg + errMsg, null, null, responseData);
 		}
@@ -194,17 +289,17 @@ public class KMSClient {
 					+ errMsg, null, null);
 			throw hdpException;
 		} else {
-			String kmsUrl 		= configs.get("provider");
+			String kmsUrl = configs.get("provider");
 			String kmsUserName = configs.get("username");
 			String kmsPassWord = configs.get("password");
-			kmsClient 			= new KMSClient (kmsUrl, kmsUserName,
-										 		  kmsPassWord);
-	
+			kmsClient = new KMSClient(kmsUrl, kmsUserName, kmsPassWord);
+
 		}
 		return kmsClient;
 	}
 
-	public static List<String> getKmsKey (final KMSClient kmsClient, String keyName, List<String> existingKeyName) {
+	public static List<String> getKmsKey(final KMSClient kmsClient,
+			String keyName, List<String> existingKeyName) {
 
 		List<String> resultList = new ArrayList<String>();
 		String errMsg = errMessage;
@@ -221,10 +316,12 @@ public class KMSClient {
 
 			if (keyName != null) {
 				String finalkmsKeyName = keyName.trim();
-				resultList = kmsClient.getKeyList(finalkmsKeyName,existingKeyName);
+				resultList = kmsClient.getKeyList(finalkmsKeyName,
+						existingKeyName);
 				if (resultList != null) {
 					if (LOG.isDebugEnabled()) {
-						LOG.debug("Returning list of " + resultList.size() + " Kms Keys");
+						LOG.debug("Returning list of " + resultList.size()
+								+ " Kms Keys");
 					}
 				}
 			}
@@ -232,13 +329,14 @@ public class KMSClient {
 			resultList = null;
 			throw he;
 		} catch (Exception e) {
-			String msgDesc = "Unable to get a valid response from the provider";
+			String msgDesc = "Unable to get a valid response from the provider : "+e.getMessage();
 			LOG.error(msgDesc, e);
 			HadoopException hdpException = new HadoopException(msgDesc);
-			hdpException.generateResponseDataMap(false, msgDesc, msgDesc + errMsg, null, null);
+			hdpException.generateResponseDataMap(false, msgDesc, msgDesc
+					+ errMsg, null, null);
 			resultList = null;
 			throw hdpException;
 		}
 		return resultList;
-	}	
-}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/14ec7d52/security-admin/src/main/java/org/apache/ranger/biz/KmsKeyMgr.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/KmsKeyMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/KmsKeyMgr.java
index 5f2d4af..7446d1e 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/KmsKeyMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/KmsKeyMgr.java
@@ -19,9 +19,15 @@
 
 package org.apache.ranger.biz;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 import javax.servlet.http.HttpServletRequest;
@@ -32,6 +38,8 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.collections.Predicate;
 import org.apache.commons.collections.PredicateUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.ProviderUtils;
 import org.apache.log4j.Logger;
 import org.apache.ranger.common.ContextUtil;
 import org.apache.ranger.common.MessageEnums;
@@ -46,10 +54,11 @@ import org.apache.ranger.view.VXKmsKeyList;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import com.google.common.base.Strings;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
 import com.sun.jersey.api.client.WebResource;
 import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
@@ -65,6 +74,8 @@ public class KmsKeyMgr {
 	private static final String KMS_DELETE_KEY_URI 		= "v1/key/${alias}?user.name=${userName}";			//DELETE
 	private static final String KMS_KEY_METADATA_URI 	= "v1/key/${alias}/_metadata?user.name=${userName}";  //GET
 	private static final String KMS_URL_CONFIG 			= "provider"; 
+	private static Map<String, String> providerList = new HashMap<String, String>(); 
+	private static int nextProvider = 0;
 	
 	@Autowired
 	ServiceDBStore svcStore;	
@@ -75,28 +86,46 @@ public class KmsKeyMgr {
 	@Autowired
 	RangerConfigUtil configUtil;
 	
+	@SuppressWarnings("unchecked")
 	public VXKmsKeyList searchKeys(String repoName){
-		String provider = null;
+		String providers[] = null;
 		try {
-			provider = getKMSURL(repoName);
+			providers = getKMSURL(repoName);
 		} catch (Exception e) {
 			logger.error("getKey(" + repoName + ") failed", e);
 		}
-		Client c = getClient() ;
-		String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
-		String keyLists = KMS_KEY_LIST_URI.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
-		String uri = provider + (provider.endsWith("/") ? keyLists : ("/" + keyLists));		
+		List<VXKmsKey> vXKeys = new ArrayList<VXKmsKey>();
 		VXKmsKeyList vxKmsKeyList = new VXKmsKeyList();
-		WebResource r = c.resource(uri) ;
-		String response = r.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
-		Gson gson = new GsonBuilder().create() ;
-		logger.debug(" Search Key RESPONSE: [" + response + "]") ;
-		List<VXKmsKey> vXKeys = new ArrayList<VXKmsKey>();	    
-		@SuppressWarnings("unchecked")
-		List<String> keys = gson.fromJson(response, List.class) ;
-		if(keys != null && keys.size() > 0){
-			for(String name : keys){
-				VXKmsKey key = getKey(repoName, name);
+		List<String> keys = null;
+		String connProvider = null;
+		for (int i = 0; i < providers.length; i++) {
+			Client c = getClient();
+			String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
+			String keyLists = KMS_KEY_LIST_URI.replaceAll(
+					Pattern.quote("${userName}"), currentUserLoginId);
+			connProvider = providers[i];
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? keyLists : ("/" + keyLists));
+
+			WebResource r = c.resource(uri);
+			try {
+				String response = r.accept(MediaType.APPLICATION_JSON_TYPE)
+						.get(String.class);
+				Gson gson = new GsonBuilder().create();
+				logger.debug(" Search Key RESPONSE: [" + response + "]");
+
+				keys = gson.fromJson(response, List.class);
+				break;
+			} catch (Exception e) {
+				if (e instanceof UniformInterfaceException || i == providers.length - 1)
+					throw e;								
+				else
+					continue;
+			}
+		}
+		if (keys != null && keys.size() > 0) {
+			for (String name : keys) {
+				VXKmsKey key = getKeyFromUri(connProvider, name);
 				vXKeys.add(key);
 			}
 			vxKmsKeyList.setResultSize(vXKeys.size());
@@ -105,102 +134,252 @@ public class KmsKeyMgr {
 			vxKmsKeyList.setPageSize(vXKeys.size());
 		}
 		vxKmsKeyList.setVXKeys(vXKeys);
-	    return vxKmsKeyList;
+		return vxKmsKeyList;
 	}
 
 	public VXKmsKey rolloverKey(String provider, VXKmsKey vXKey){
+		String providers[] = null;
 		try {
-			provider = getKMSURL(provider);
+			providers = getKMSURL(provider);
 		} catch (Exception e) {
-			logger.error("rolloverKey(" + provider + ", "+ vXKey.getName() +") failed", e);
+			logger.error("rolloverKey(" + provider + ", " + vXKey.getName()
+					+ ") failed", e);
 		}
-		VXKmsKey ret = null ;
-		Client c = getClient() ;
-		String rollRest = KMS_ROLL_KEY_URI.replaceAll(Pattern.quote("${alias}"), vXKey.getName());
-		String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
-		rollRest = rollRest.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
-		String uri = provider + (provider.endsWith("/") ? rollRest : ("/" + rollRest));
-		WebResource r = c.resource(uri) ;
-		Gson gson = new GsonBuilder().create() ;
-		String jsonString = gson.toJson(vXKey) ;
-		String response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE).post(String.class, jsonString) ;
-		logger.debug("Roll RESPONSE: [" + response + "]") ;
-		ret = gson.fromJson(response, VXKmsKey.class) ;
-		return ret ;
+		VXKmsKey ret = null;
+		for (int i = 0; i < providers.length; i++) {
+			Client c = getClient();
+			String rollRest = KMS_ROLL_KEY_URI.replaceAll(
+					Pattern.quote("${alias}"), vXKey.getName());
+			String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
+			rollRest = rollRest.replaceAll(Pattern.quote("${userName}"),
+					currentUserLoginId);
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? rollRest : ("/" + rollRest));
+			WebResource r = c.resource(uri);
+			Gson gson = new GsonBuilder().create();
+			String jsonString = gson.toJson(vXKey);
+			try {
+				String response = r.accept(MediaType.APPLICATION_JSON_TYPE)
+						.type(MediaType.APPLICATION_JSON_TYPE)
+						.post(String.class, jsonString);
+				logger.debug("Roll RESPONSE: [" + response + "]");
+				ret = gson.fromJson(response, VXKmsKey.class);
+				break;
+			} catch (Exception e) {
+				if (e instanceof UniformInterfaceException || i == providers.length - 1)
+					throw e;								
+				else
+					continue;
+			}
+		}
+		return ret;
 	}
 
 	public void deleteKey(String provider, String name){
+		String providers[] = null;
 		try {
-			provider = getKMSURL(provider);
+			providers = getKMSURL(provider);
 		} catch (Exception e) {
-			logger.error("deleteKey(" + provider + ", "+ name +") failed", e);
+			logger.error("deleteKey(" + provider + ", " + name + ") failed", e);
 		}
-		Client c = getClient() ;
-		String deleteRest = KMS_DELETE_KEY_URI.replaceAll(Pattern.quote("${alias}"), name);
-		String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
-		deleteRest = deleteRest.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
-		String uri = provider + (provider.endsWith("/") ? deleteRest : ("/" + deleteRest));
-		WebResource r = c.resource(uri) ;
-		String response = r.delete(String.class) ;
-		logger.debug("delete RESPONSE: [" + response + "]") ;			
+		for (int i = 0; i < providers.length; i++) {
+			Client c = getClient();
+			String deleteRest = KMS_DELETE_KEY_URI.replaceAll(
+					Pattern.quote("${alias}"), name);
+			String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
+			deleteRest = deleteRest.replaceAll(Pattern.quote("${userName}"),
+					currentUserLoginId);
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? deleteRest
+							: ("/" + deleteRest));
+			WebResource r = c.resource(uri);
+			try {
+				String response = r.delete(String.class) ;
+				logger.debug("delete RESPONSE: [" + response + "]") ;	
+				break;
+			} catch (Exception e) {
+				if (e instanceof UniformInterfaceException || i == providers.length - 1)
+					throw e;								
+				else
+					continue;
+			}
+		}			
 	}
 
 	public VXKmsKey createKey(String provider, VXKmsKey vXKey){
+		String providers[] = null;
 		try {
-			provider = getKMSURL(provider);
+			providers = getKMSURL(provider);
 		} catch (Exception e) {
-			logger.error("createKey(" + provider + ", "+ vXKey.getName() +") failed", e);
+			logger.error("createKey(" + provider + ", " + vXKey.getName()
+					+ ") failed", e);
 		}
-		VXKmsKey ret = null ;
-		Client c = getClient() ;
-		String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
-		String createRest = KMS_ADD_KEY_URI.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
-		String uri = provider + (provider.endsWith("/") ? createRest : ("/" + createRest));
-		WebResource r = c.resource(uri) ;
-		Gson gson = new GsonBuilder().create() ;
-		String jsonString = gson.toJson(vXKey) ;
-        String response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE).post(String.class, jsonString) ;
-        logger.debug("Create RESPONSE: [" + response + "]") ;
-        ret = gson.fromJson(response, VXKmsKey.class) ;
-	    return ret ;		
+		VXKmsKey ret = null;
+		for (int i = 0; i < providers.length; i++) {
+			Client c = getClient();
+			String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
+			String createRest = KMS_ADD_KEY_URI.replaceAll(
+					Pattern.quote("${userName}"), currentUserLoginId);
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? createRest
+							: ("/" + createRest));
+			WebResource r = c.resource(uri);
+			Gson gson = new GsonBuilder().create();
+			String jsonString = gson.toJson(vXKey);
+			try {
+				String response = r.accept(MediaType.APPLICATION_JSON_TYPE)
+						.type(MediaType.APPLICATION_JSON_TYPE)
+						.post(String.class, jsonString);
+				logger.debug("Create RESPONSE: [" + response + "]");
+				ret = gson.fromJson(response, VXKmsKey.class);
+				return ret;
+			} catch (Exception e) {
+				if (e instanceof UniformInterfaceException || i == providers.length - 1)
+					throw e;								
+				else
+					continue;
+			}
+		}
+		return ret;	
 	}
 	
 	public VXKmsKey getKey(String provider, String name){
+		String providers[] = null;
 		try {
-			provider = getKMSURL(provider);
+			providers = getKMSURL(provider);
 		} catch (Exception e) {
-			logger.error("getKey(" + provider + ", "+ name +") failed", e);
+			logger.error("getKey(" + provider + ", " + name + ") failed", e);
+		}
+		for (int i = 0; i < providers.length; i++) {
+			Client c = getClient();
+			String keyRest = KMS_KEY_METADATA_URI.replaceAll(
+					Pattern.quote("${alias}"), name);
+			String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
+			keyRest = keyRest.replaceAll(Pattern.quote("${userName}"),
+					currentUserLoginId);
+			String uri = providers[i]
+					+ (providers[i].endsWith("/") ? keyRest : ("/" + keyRest));
+			WebResource r = c.resource(uri);
+			try {
+				String response = r.accept(MediaType.APPLICATION_JSON_TYPE)
+						.get(String.class);
+				Gson gson = new GsonBuilder().create();
+				logger.debug("RESPONSE: [" + response + "]");
+				VXKmsKey key = gson.fromJson(response, VXKmsKey.class);
+				return key;
+			} catch (Exception e) {
+				if (e instanceof UniformInterfaceException || i == providers.length - 1)
+					throw e;								
+				else
+					continue;
+			}
 		}
-		Client c = getClient() ;
-		String keyRest = KMS_KEY_METADATA_URI.replaceAll(Pattern.quote("${alias}"), name);
+		return null;
+	}
+	
+	public VXKmsKey getKeyFromUri(String provider, String name) {
+		Client c = getClient();
+		String keyRest = KMS_KEY_METADATA_URI.replaceAll(
+				Pattern.quote("${alias}"), name);
 		String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
-		keyRest = keyRest.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
+		keyRest = keyRest.replaceAll(Pattern.quote("${userName}"),
+				currentUserLoginId);
 		String uri = provider + (provider.endsWith("/") ? keyRest : ("/" + keyRest));
-		WebResource r = c.resource(uri) ;
+		WebResource r = c.resource(uri);
 		String response = r.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
-		Gson gson = new GsonBuilder().create() ;
-		logger.debug("RESPONSE: [" + response + "]") ;
-		VXKmsKey key = gson.fromJson(response, VXKmsKey.class) ;
-		return key;
+		Gson gson = new GsonBuilder().create();
+		logger.debug("RESPONSE: [" + response + "]");
+		VXKmsKey key = gson.fromJson(response, VXKmsKey.class);
+		return key;			
 	}
 	
-	private String getKMSURL(String name) throws Exception{
-		String provider = null;
+	private String[] getKMSURL(String name) throws Exception{
+		String providers[] = null;
 		RangerService rangerService = null;
 		try {
 			rangerService = svcStore.getServiceByName(name);
-			provider = rangerService.getConfigs().get(KMS_URL_CONFIG);
-			provider = provider.replaceAll("kms://","");
-			provider = provider.replaceAll("http@","http://");
-		} catch(Exception excp) {
+			String kmsUrl = rangerService.getConfigs().get(KMS_URL_CONFIG);
+			String dbKmsUrl = kmsUrl;
+			if(providerList.containsKey(kmsUrl)){
+				kmsUrl = providerList.get(kmsUrl);				
+			}else{
+				providerList.put(kmsUrl, kmsUrl);
+			}
+			providers = createProvider(dbKmsUrl,kmsUrl);
+		} catch (Exception excp) {
 			logger.error("getServiceByName(" + name + ") failed", excp);
 			throw new Exception("getServiceByName(" + name + ") failed", excp);
 		}
 
-		if(rangerService == null || provider == null) {
-			throw new Exception("Provider "+provider+" not found");
+		if (rangerService == null || providers == null) {
+			throw new Exception("Provider " + name + " not found");
+		}
+		return providers;
+	}
+	
+	private String[] createProvider(String dbKmsUrl, String uri) throws IOException,URISyntaxException {		
+		URI providerUri = new URI(uri);
+		URL origUrl = new URL(extractKMSPath(providerUri).toString());
+		String authority = origUrl.getAuthority();
+		// 	check for ';' which delimits the backup hosts
+		if (Strings.isNullOrEmpty(authority)) {
+			throw new IOException("No valid authority in kms uri [" + origUrl+ "]");
+		}
+		// 	Check if port is present in authority
+		// 	In the current scheme, all hosts have to run on the same port
+		int port = -1;
+		String hostsPart = authority;
+		if (authority.contains(":")) {
+			String[] t = authority.split(":");
+			try {
+				port = Integer.parseInt(t[1]);
+			} catch (Exception e) {
+				throw new IOException("Could not parse port in kms uri ["
+				+ origUrl + "]");
+			}
+			hostsPart = t[0];
+		}
+		return createProvider(dbKmsUrl, providerUri, origUrl, port, hostsPart);
+	}
+
+	private static Path extractKMSPath(URI uri) throws MalformedURLException,IOException {
+		return ProviderUtils.unnestUri(uri);
+	}
+
+	private String[] createProvider(String dbkmsUrl, URI providerUri, URL origUrl, int port,
+			String hostsPart) throws IOException {
+		String[] hosts = hostsPart.split(";");
+		String[] providers = new String[hosts.length];
+		if (hosts.length == 1) {
+			providers[0] = origUrl.toString();
+		} else {
+			String providerNext=providerUri.getScheme()+"://"+origUrl.getProtocol()+"@";
+			for(int i=nextProvider; i<hosts.length; i++){
+				providerNext = providerNext+hosts[i];
+				if(i!=(hosts.length-1)){
+					providerNext = providerNext+";";
+				}
+			}
+			for(int i=0; i<nextProvider; i++){
+				providerNext = providerNext+";"+hosts[i];
+			}
+			if(nextProvider != hosts.length-1){
+				nextProvider = nextProvider+1;
+			}else{
+				nextProvider = 0;
+			}
+			providerNext = providerNext +":"+port+origUrl.getPath();
+			providerList.put(dbkmsUrl, providerNext);
+			for (int i = 0; i < hosts.length; i++) {
+				try {
+					String url = origUrl.getProtocol()+"://"+hosts[i]+":"+port+origUrl.getPath();
+					providers[i] = new URI(url).toString();
+				} catch (URISyntaxException e) {
+					throw new IOException("Could not Prase KMS URL..", e);
+				}
+			}
 		}
-		return provider;
+		return providers;
 	}
 
 	private synchronized Client getClient() {