Repository: ranger Updated Branches: refs/heads/master 4603dfa3d -> 9fea06dbb
RANGER-1271 Ranger-Atlas testConnection feature Signed-off-by: Velmurugan Periasamy <v...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/306075df Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/306075df Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/306075df Branch: refs/heads/master Commit: 306075df553e295041ef5b6e5b01a8a6799c9654 Parents: 4603dfa Author: zhangqiang2 <zhangqia...@zte.com.cn> Authored: Thu Jan 5 23:15:12 2017 +0800 Committer: Velmurugan Periasamy <v...@apache.org> Committed: Thu Feb 2 23:29:53 2017 -0500 ---------------------------------------------------------------------- .../services/atlas/RangerServiceAtlas.java | 50 +++- .../services/atlas/client/AtlasClient.java | 292 +++++++++++++++++++ .../atlas/client/AtlasConnectionMgr.java | 30 ++ .../services/atlas/client/AtlasResourceMgr.java | 88 ++++++ src/main/assembly/admin-web.xml | 16 +- 5 files changed, 464 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ranger/blob/306075df/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/RangerServiceAtlas.java ---------------------------------------------------------------------- diff --git a/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/RangerServiceAtlas.java b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/RangerServiceAtlas.java index cb5a7eb..ba4d263 100644 --- a/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/RangerServiceAtlas.java +++ b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/RangerServiceAtlas.java @@ -21,14 +21,15 @@ package org.apache.ranger.services.atlas; import java.util.ArrayList; import java.util.HashMap; import java.util.List; - +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.ranger.plugin.client.BaseClient; import org.apache.ranger.plugin.model.RangerService; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.service.RangerBaseService; import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.services.atlas.client.AtlasResourceMgr; + public class RangerServiceAtlas extends RangerBaseService { @@ -44,19 +45,46 @@ public class RangerServiceAtlas extends RangerBaseService { } @Override - public HashMap<String, Object> validateConfig() throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("This method will be implemented"); - } + public HashMap<String,Object> validateConfig() throws Exception { HashMap<String, Object> responseMap = new HashMap<String, Object>(); - String msg = "This feature is not available currently"; - BaseClient.generateResponseDataMap(true, msg, msg, null, null, responseMap); + String serviceName = getServiceName(); + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceAtlas.validateConfig Service: (" + serviceName + " )"); + } + if ( configs != null) { + try { + responseMap = AtlasResourceMgr.validateConfig(serviceName, configs); + } catch (Exception e) { + LOG.error("<== RangerServiceAtlas.validateConfig Error:" + e); + throw e; + } + } + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceAtlas.validateConfig Response : (" + responseMap + " )"); + } return responseMap; } + @Override public List<String> lookupResource(ResourceLookupContext context) throws Exception { - //This feature is not available currently - return new ArrayList<String>(); - } + List<String> ret = new ArrayList<String>(); + String serviceName = getServiceName(); + Map<String,String> configs = getConfigs(); + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceAtlas.lookupResource Context: (" + context + ")"); + } + if (context != null) { + try { + ret = AtlasResourceMgr.getAtlasTermResources(serviceName,configs,context); + } catch (Exception e) { + LOG.error( "<==RangerServiceAtlas.lookupResource Error : " + e); + throw e; + } + } + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceAtlas.lookupResource Response: (" + ret + ")"); + } + return ret; + } } http://git-wip-us.apache.org/repos/asf/ranger/blob/306075df/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasClient.java ---------------------------------------------------------------------- diff --git a/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasClient.java b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasClient.java new file mode 100644 index 0000000..4f90469 --- /dev/null +++ b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasClient.java @@ -0,0 +1,292 @@ +/* + * 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. + */ + +package org.apache.ranger.services.atlas.client; + +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import javax.security.auth.Subject; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.NewCookie; + +import org.apache.log4j.Logger; +import org.apache.ranger.plugin.client.BaseClient; +import org.apache.ranger.plugin.client.HadoopException; +import org.apache.ranger.plugin.util.PasswordUtils; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class AtlasClient extends BaseClient { + + private static final Logger LOG = Logger.getLogger(AtlasClient.class); + private static final String EXPECTED_MIME_TYPE = "application/json"; + private static final String ATLAS_STATUS_API_ENDPOINT = "/j_spring_security_check"; + private static final String ATLAS_LIST_TERM_API_ENDPOINT = "/api/atlas/types"; + 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 ranger_admin.log for more info."; + + private String atlasUrl; + private String userName; + private String password; + + public AtlasClient(String serviceName, Map<String, String> configs) { + + super(serviceName,configs,"atlas-client"); + + this.atlasUrl = configs.get("atlas.rest.address"); + this.userName = configs.get("username"); + this.password = configs.get("password"); + if (this.atlasUrl == null || this.atlasUrl.isEmpty()) { + LOG.error("No value found for configuration 'atlas.rest.address'. Atlas resource lookup will fail"); + } + if (this.userName == null || this.userName.isEmpty()) { + LOG.error("No value found for configuration 'usename'. Atlas resource lookup will fail"); + } + if (this.password == null || this.password.isEmpty()) { + LOG.error("No value found for configuration 'password'. Atlas resource lookup will fail"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Atlas Client is build with url [" + this.atlasUrl + "] user: [" + this.userName + "], password: [" + "*********" + "]"); + } + } + + public List<String> getTermList( String termNameMatching, List<String> existingTermList) { + if (LOG.isDebugEnabled()) { + LOG.debug("Getting Atlas Terms list for termNameMatching : " + termNameMatching); + } + final String errMsg = errMessage; + List<String> ret = null; + + Callable<List<String>> callableAtlasTermListGetter = new Callable<List<String>>() { + + @Override + public List<String> call() { + List<String> atlasTermListGetter = null; + + Subject subj = getLoginSubject(); + + if (subj != null) { + atlasTermListGetter = Subject.doAs(subj, new PrivilegedAction<List<String>>() { + + @Override + public List<String> run() { + + List<String> lret = new ArrayList<String>(); + + String statusUrl = atlasUrl + ATLAS_STATUS_API_ENDPOINT; + String resultUrl = atlasUrl + ATLAS_LIST_TERM_API_ENDPOINT; + + Client client = null; + ClientResponse statusResponse = null; + ClientResponse resultResponse = null; + + try { + client = Client.create(); + WebResource webResource = client.resource(statusUrl); + MultivaluedMap<String, String> formData = new MultivaluedMapImpl(); + formData.add("j_username", userName); + formData.add("j_password",PasswordUtils.decryptPassword(password)); + try { + statusResponse = webResource.type("application/x-www-form-urlencoded").post( + ClientResponse.class, formData); + } catch (Exception e) { + String msgDesc = "Unable to get a valid statusResponse for " + + "expected mime type : [" + EXPECTED_MIME_TYPE + + "] URL : " + statusUrl + " - got null response."; + LOG.error(msgDesc); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("getTermList():calling " + statusUrl); + } + + if (statusResponse != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("getTermList():response.getStatus()= " + statusResponse.getStatus()); + } + if (statusResponse.getStatus() == 200) { + WebResource webResource2 = client + .resource(resultUrl); + WebResource.Builder builder = webResource2.getRequestBuilder(); + for (NewCookie cook : statusResponse.getCookies()) { builder = builder.cookie(cook); + } + resultResponse = builder.get(ClientResponse.class); + lret.add(resultResponse.getEntity(String.class)); + } else{ + LOG.info("getTermList():response.getStatus()= " + statusResponse.getStatus() + " for URL " + statusUrl + ", so returning null list"); + LOG.info(statusResponse.getEntity(String.class)); + lret = null; + } + } + } catch (Throwable t) { + lret = null; + String msgDesc = "Exception while getting Atlas Term List." + + " URL : " + statusUrl; + HadoopException hdpException = new HadoopException(msgDesc, + t); + LOG.error(msgDesc, t); + hdpException.generateResponseDataMap(false, + BaseClient.getMessage(t), msgDesc + errMsg, null, + null); + throw hdpException; + + } finally { + if (statusResponse != null) { + statusResponse.close(); + } + if (resultResponse != null) { + resultResponse.close(); + } + + if (client != null) { + client.destroy(); + } + } + return lret; + } + } ); + } + return atlasTermListGetter; + } + }; + try { + ret = timedTask(callableAtlasTermListGetter, 5, TimeUnit.SECONDS); + } catch ( Throwable t) { + LOG.error("Unable to get Atlas Terms list from [" + atlasUrl + "]", t); + String msgDesc = "Unable to get a valid response for " + + "expected mime type : [" + EXPECTED_MIME_TYPE + + "] URL : " + atlasUrl; + HadoopException hdpException = new HadoopException(msgDesc, + t); + LOG.error(msgDesc, t); + + hdpException.generateResponseDataMap(false, + BaseClient.getMessage(t), msgDesc + errMsg, null, + null); + throw hdpException; + } + return ret; + } + + public static HashMap<String, Object> connectionTest(String serviceName, + Map<String, String> configs) { + + String errMsg = errMessage; + boolean connectivityStatus = false; + HashMap<String, Object> responseData = new HashMap<String, Object>(); + + AtlasClient AtlasClient = getAtlasClient(serviceName, + configs); + List<String> strList = getAtlasTermResource(AtlasClient, "",null); + + if (strList != null && strList.size() > 0 ) { + if (LOG.isDebugEnabled()) { + LOG.debug("TESTING Term list size" + strList.size() + " Atlas Terms"); + } + connectivityStatus = true; + } + + if (connectivityStatus) { + String successMsg = "ConnectionTest Successful"; + BaseClient.generateResponseDataMap(connectivityStatus, successMsg, + successMsg, null, null, responseData); + } else { + String failureMsg = "Unable to retrieve any Atlas Terms using given parameters."; + BaseClient.generateResponseDataMap(connectivityStatus, failureMsg, + failureMsg + errMsg, null, null, responseData); + } + + return responseData; + } + + public static AtlasClient getAtlasClient(String serviceName, + Map<String, String> configs) { + AtlasClient AtlasClient = null; + if (LOG.isDebugEnabled()) { + LOG.debug("Getting AtlasClient for datasource: " + serviceName); + } + String errMsg = errMessage; + if (configs == null || configs.isEmpty()) { + String msgDesc = "Could not connect as Connection ConfigMap is empty."; + LOG.error(msgDesc); + HadoopException hdpException = new HadoopException(msgDesc); + hdpException.generateResponseDataMap(false, msgDesc, msgDesc + + errMsg, null, null); + throw hdpException; + } else { + AtlasClient = new AtlasClient (serviceName, configs); + } + return AtlasClient; + } + + public static List<String> getAtlasTermResource (final AtlasClient atlasClient, + String atlasTermName, List<String> existingAtlasTermName) { + + List<String> resultList = new ArrayList<String>(); + String errMsg = errMessage; + + try { + if (atlasClient == null) { + String msgDesc = "Unable to get Atlas Terms : AtlasClient is null."; + LOG.error(msgDesc); + HadoopException hdpException = new HadoopException(msgDesc); + hdpException.generateResponseDataMap(false, msgDesc, msgDesc + + errMsg, null, null); + throw hdpException; + } + + if (atlasTermName != null) { + String finalAtlasTermName = atlasTermName.trim(); + resultList = atlasClient + .getTermList(finalAtlasTermName,existingAtlasTermName); + if (resultList != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Returning list of " + resultList.size() + " Atlas Terms"); + } + } + } + }catch (Throwable t) { + String msgDesc = "getAtlasResource: Unable to get Atlas resources."; + LOG.error(msgDesc, t); + HadoopException hdpException = new HadoopException(msgDesc); + + hdpException.generateResponseDataMap(false, + BaseClient.getMessage(t), msgDesc + errMsg, null, null); + throw hdpException; + } + + return resultList; + } + + public static <T> T timedTask(Callable<T> callableObj, long timeout, + TimeUnit timeUnit) throws Exception { + return callableObj.call(); + } +} http://git-wip-us.apache.org/repos/asf/ranger/blob/306075df/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasConnectionMgr.java ---------------------------------------------------------------------- diff --git a/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasConnectionMgr.java b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasConnectionMgr.java new file mode 100644 index 0000000..84e24c5 --- /dev/null +++ b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasConnectionMgr.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.ranger.services.atlas.client; + +import java.util.Map; + +public class AtlasConnectionMgr { + + public static AtlasClient getAtlasClient(String serviceName, Map<String, String> configs) { + return new AtlasClient(serviceName, configs); + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/306075df/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasResourceMgr.java ---------------------------------------------------------------------- diff --git a/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasResourceMgr.java b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasResourceMgr.java new file mode 100644 index 0000000..f738601 --- /dev/null +++ b/plugin-atlas/src/main/java/org/apache/ranger/services/atlas/client/AtlasResourceMgr.java @@ -0,0 +1,88 @@ +/* + * 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. + */ + +package org.apache.ranger.services.atlas.client; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.ranger.plugin.service.ResourceLookupContext; + + +public class AtlasResourceMgr { + public static final Logger LOG = Logger.getLogger(AtlasResourceMgr.class); + private static final String ATLASTERM = "terms"; + + public static HashMap<String, Object> validateConfig(String serviceName, Map<String, String> configs) throws Exception { + + HashMap<String, Object> ret = null; + + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasResourceMgr.validateConfig ServiceName: "+ serviceName + "Configs" + configs ); + } + + try { + ret = AtlasClient.connectionTest(serviceName, configs); + } catch (Exception e) { + LOG.error("<== AtlasResourceMgr.validateConfig Error: " + e); + throw e; + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasResourceMgr.validateConfig Result : "+ ret ); + } + return ret; + } + + public static List<String> getAtlasTermResources(String serviceName, Map<String, String> configs,ResourceLookupContext context) { + String userInput = context.getUserInput(); + Map<String, List<String>> resourceMap = context.getResources(); + List<String> resultList = null; + List<String> atlasTermList = null; + String atlasTermName = null; + + if ( resourceMap != null && !resourceMap.isEmpty() && + resourceMap.get(ATLASTERM) != null ) { + atlasTermName = userInput; + atlasTermList = resourceMap.get(ATLASTERM); + } else { + atlasTermName = userInput; + } + + if (configs == null || configs.isEmpty()) { + LOG.error("Connection Config is empty"); + } else { + resultList = getAtlasTermResource(serviceName, configs, atlasTermName,atlasTermList); + } + return resultList; + } + + public static List<String> getAtlasTermResource(String serviceName, Map<String, String> configs, String atlasTermName, List<String> atlasTermList) { + final AtlasClient atlasClient = AtlasConnectionMgr.getAtlasClient(serviceName, configs); + List<String> termList = null; + if (atlasClient != null) { + synchronized(atlasClient) { + termList = atlasClient.getTermList(atlasTermName, atlasTermList); + } + } + return termList; + } +} http://git-wip-us.apache.org/repos/asf/ranger/blob/306075df/src/main/assembly/admin-web.xml ---------------------------------------------------------------------- diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml index 4779071..966033f 100644 --- a/src/main/assembly/admin-web.xml +++ b/src/main/assembly/admin-web.xml @@ -310,7 +310,21 @@ <include>org.apache.ranger:ranger-nifi-plugin</include> </includes> </moduleSet> - </moduleSets> + + <moduleSet> + <binaries> + <includeDependencies>true</includeDependencies> + <outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/atlas</outputDirectory> + <unpack>false</unpack> + <directoryMode>755</directoryMode> + <fileMode>644</fileMode> + </binaries> + <includes> + <include>org.apache.ranger:ranger-atlas-plugin</include> + </includes> + </moduleSet> + + </moduleSets> <fileSets> <fileSet>