RANGER-504: Fixed KMS Client to handle multiple KMS instances in URL Signed-off-by: sneethiraj <[email protected]>
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/tag-policy Commit: 14ec7d526b344a597f81b31613416c383c94f467 Parents: 0421271 Author: Velmurugan Periasamy <[email protected]> Authored: Fri May 22 20:15:03 2015 -0400 Committer: sneethiraj <[email protected]> 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() {
