This is an automated email from the ASF dual-hosted git repository. spolavarapu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new 8840310 RANGER-2862: added Java client library for Ranger REST APIs new 64a1d8e Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/ranger into RANGER-2862-1 8840310 is described below commit 88403100b3c56d0cf41cfb8ac47a0315ab830cad Author: Abhishek Kumar <abhishekkumar100...@gmail.com> AuthorDate: Mon Jul 6 20:16:03 2020 -0400 RANGER-2862: added Java client library for Ranger REST APIs Signed-off-by: Sailaja Polavarapu <spolavar...@cloudera.com> --- intg/pom.xml | 51 ++ .../main/java/org/apache/ranger/RangerClient.java | 530 +++++++++++++++++++++ .../org/apache/ranger/RangerServiceException.java | 44 ++ intg/src/main/resources/log4j.properties | 23 + .../java/org/apache/ranger/TestRangerClient.java | 150 ++++++ pom.xml | 17 + ranger-examples/distro/pom.xml | 3 +- .../distro/src/main/assembly/sample-client.xml | 92 ++++ ranger-examples/pom.xml | 1 + ranger-examples/sample-client/pom.xml | 60 +++ .../sample-client/scripts/run-sample-client.sh | 50 ++ .../ranger/examples/sampleclient/SampleClient.java | 193 ++++++++ .../src/main/resources/log4j.properties | 23 + 13 files changed, 1236 insertions(+), 1 deletion(-) diff --git a/intg/pom.xml b/intg/pom.xml new file mode 100644 index 0000000..da8b910 --- /dev/null +++ b/intg/pom.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <packaging>jar</packaging> + <parent> + <artifactId>ranger</artifactId> + <groupId>org.apache.ranger</groupId> + <version>2.1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>ranger-intg</artifactId> + <dependencies> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-plugins-common</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> + </dependencies> +</project> \ No newline at end of file diff --git a/intg/src/main/java/org/apache/ranger/RangerClient.java b/intg/src/main/java/org/apache/ranger/RangerClient.java new file mode 100644 index 0000000..29b2ec0 --- /dev/null +++ b/intg/src/main/java/org/apache/ranger/RangerClient.java @@ -0,0 +1,530 @@ +/* + * 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; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.sun.jersey.api.client.ClientResponse; +import org.apache.hadoop.conf.Configuration; +import org.apache.ranger.plugin.model.*; +import org.apache.ranger.admin.client.datatype.RESTResponse; +import org.apache.ranger.plugin.util.GrantRevokeRoleRequest; +import org.apache.ranger.plugin.util.RangerRESTClient; + +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.net.URI; +import java.util.*; + + +public class RangerClient { + private static final Logger LOG = LoggerFactory.getLogger(RangerClient.class); + + // QueryParams + private static final String PARAM_DAYS = "days"; + private static final String PARAM_EXEC_USER = "execUser"; + private static final String PARAM_POLICY_NAME = "policyname"; + private static final String PARAM_SERVICE_NAME = "serviceName"; + private static final String PARAM_RELOAD_SERVICE_POLICIES_CACHE = "reloadServicePoliciesCache"; + + // URIs + private static final String URI_BASE = "/service/public/v2/api"; + + private static final String URI_SERVICEDEF = URI_BASE + "/servicedef"; + private static final String URI_SERVICEDEF_BY_ID = URI_SERVICEDEF + "/%d"; + private static final String URI_SERVICEDEF_BY_NAME = URI_SERVICEDEF + "/name/%s"; + + private static final String URI_SERVICE = URI_BASE + "/service"; + private static final String URI_SERVICE_BY_ID = URI_SERVICE + "/%d"; + private static final String URI_SERVICE_BY_NAME = URI_SERVICE + "/name/%s"; + private static final String URI_POLICIES_IN_SERVICE = URI_SERVICE + "/%s/policy"; + + private static final String URI_POLICY = URI_BASE + "/policy"; + private static final String URI_APPLY_POLICY = URI_POLICY + "/apply"; + private static final String URI_POLICY_BY_ID = URI_POLICY + "/%d"; + private static final String URI_POLICY_BY_NAME = URI_SERVICE + "/%s/policy/%s"; + + private static final String URI_ROLE = URI_BASE + "/roles"; + private static final String URI_ROLE_NAMES = URI_ROLE + "/names"; + private static final String URI_ROLE_BY_ID = URI_ROLE + "/%d"; + private static final String URI_ROLE_BY_NAME = URI_ROLE + "/name/%s"; + private static final String URI_USER_ROLES = URI_ROLE + "/user/%s"; + private static final String URI_GRANT_ROLE = URI_ROLE + "/grant/%s"; + private static final String URI_REVOKE_ROLE = URI_ROLE + "/revoke/%s"; + + private static final String URI_ZONE = URI_BASE + "/zones"; + private static final String URI_ZONE_BY_ID = URI_ZONE + "/%d"; + private static final String URI_ZONE_BY_NAME = URI_ZONE + "/name/%s"; + + private static final String URI_PLUGIN_INFO = URI_BASE + "/plugins/info"; + private static final String URI_POLICY_DELTAS = URI_BASE + "/server/policydeltas"; + + + // APIs + public static final API CREATE_SERVICEDEF = new API(URI_SERVICEDEF, HttpMethod.POST, Response.Status.OK); + public static final API UPDATE_SERVICEDEF_BY_ID = new API(URI_SERVICEDEF_BY_ID, HttpMethod.PUT, Response.Status.OK); + public static final API UPDATE_SERVICEDEF_BY_NAME = new API(URI_SERVICEDEF_BY_NAME, HttpMethod.PUT, Response.Status.OK); + public static final API DELETE_SERVICEDEF_BY_ID = new API(URI_SERVICEDEF_BY_ID, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API DELETE_SERVICEDEF_BY_NAME = new API(URI_SERVICEDEF_BY_NAME, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API GET_SERVICEDEF_BY_ID = new API(URI_SERVICEDEF_BY_ID, HttpMethod.GET, Response.Status.OK); + public static final API GET_SERVICEDEF_BY_NAME = new API(URI_SERVICEDEF_BY_NAME, HttpMethod.GET, Response.Status.OK); + public static final API FIND_SERVICEDEFS = new API(URI_SERVICEDEF, HttpMethod.GET, Response.Status.OK); + + public static final API CREATE_SERVICE = new API(URI_SERVICE, HttpMethod.POST, Response.Status.OK); + public static final API UPDATE_SERVICE_BY_ID = new API(URI_SERVICE_BY_ID, HttpMethod.PUT, Response.Status.OK); + public static final API UPDATE_SERVICE_BY_NAME = new API(URI_SERVICE_BY_NAME, HttpMethod.PUT, Response.Status.OK); + public static final API DELETE_SERVICE_BY_ID = new API(URI_SERVICE_BY_ID, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API DELETE_SERVICE_BY_NAME = new API(URI_SERVICE_BY_NAME, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API GET_SERVICE_BY_ID = new API(URI_SERVICE_BY_ID, HttpMethod.GET, Response.Status.OK); + public static final API GET_SERVICE_BY_NAME = new API(URI_SERVICE_BY_NAME, HttpMethod.GET, Response.Status.OK); + public static final API FIND_SERVICES = new API(URI_SERVICE, HttpMethod.GET, Response.Status.OK); + + public static final API CREATE_POLICY = new API(URI_POLICY, HttpMethod.POST, Response.Status.OK); + public static final API UPDATE_POLICY_BY_ID = new API(URI_POLICY_BY_ID, HttpMethod.PUT, Response.Status.OK); + public static final API UPDATE_POLICY_BY_NAME = new API(URI_POLICY_BY_NAME, HttpMethod.PUT, Response.Status.OK); + public static final API APPLY_POLICY = new API(URI_APPLY_POLICY, HttpMethod.POST, Response.Status.OK); + public static final API DELETE_POLICY_BY_ID = new API(URI_POLICY_BY_ID, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API DELETE_POLICY_BY_NAME = new API(URI_POLICY, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API GET_POLICY_BY_ID = new API(URI_POLICY_BY_ID, HttpMethod.GET, Response.Status.OK); + public static final API GET_POLICY_BY_NAME = new API(URI_POLICY_BY_NAME, HttpMethod.GET, Response.Status.OK); + public static final API GET_POLICIES_IN_SERVICE = new API(URI_POLICIES_IN_SERVICE, HttpMethod.GET, Response.Status.OK); + public static final API FIND_POLICIES = new API(URI_POLICY, HttpMethod.GET, Response.Status.OK); + + public static final API CREATE_ZONE = new API(URI_ZONE, HttpMethod.POST, Response.Status.OK); + public static final API UPDATE_ZONE_BY_ID = new API(URI_ZONE_BY_ID, HttpMethod.PUT, Response.Status.OK); + public static final API UPDATE_ZONE_BY_NAME = new API(URI_ZONE_BY_NAME, HttpMethod.PUT, Response.Status.OK); + public static final API DELETE_ZONE_BY_ID = new API(URI_ZONE_BY_ID, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API DELETE_ZONE_BY_NAME = new API(URI_ZONE_BY_NAME, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API GET_ZONE_BY_ID = new API(URI_ZONE_BY_ID, HttpMethod.GET, Response.Status.OK); + public static final API GET_ZONE_BY_NAME = new API(URI_ZONE_BY_NAME, HttpMethod.GET, Response.Status.OK); + public static final API FIND_ZONES = new API(URI_ZONE, HttpMethod.GET, Response.Status.OK); + + public static final API CREATE_ROLE = new API(URI_ROLE, HttpMethod.POST, Response.Status.OK); + public static final API UPDATE_ROLE_BY_ID = new API(URI_ROLE_BY_ID, HttpMethod.PUT, Response.Status.OK); + public static final API DELETE_ROLE_BY_ID = new API(URI_ROLE_BY_ID, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API DELETE_ROLE_BY_NAME = new API(URI_ROLE_BY_NAME, HttpMethod.DELETE, Response.Status.NO_CONTENT); + public static final API GET_ROLE_BY_ID = new API(URI_ROLE_BY_ID, HttpMethod.GET, Response.Status.OK); + public static final API GET_ROLE_BY_NAME = new API(URI_ROLE_BY_NAME, HttpMethod.GET, Response.Status.OK); + public static final API GET_ALL_ROLE_NAMES = new API(URI_ROLE_NAMES, HttpMethod.GET, Response.Status.OK); + public static final API GET_USER_ROLES = new API(URI_USER_ROLES, HttpMethod.GET, Response.Status.OK); + public static final API GRANT_ROLE = new API(URI_GRANT_ROLE, HttpMethod.PUT, Response.Status.OK); + public static final API REVOKE_ROLE = new API(URI_REVOKE_ROLE, HttpMethod.PUT, Response.Status.OK); + public static final API FIND_ROLES = new API(URI_ROLE, HttpMethod.GET, Response.Status.OK); + + public static final API GET_PLUGIN_INFO = new API(URI_PLUGIN_INFO, HttpMethod.GET, Response.Status.OK); + public static final API DELETE_POLICY_DELTAS = new API(URI_POLICY_DELTAS, HttpMethod.DELETE, Response.Status.NO_CONTENT); + + + private final RangerRESTClient restClient; + + + public RangerClient(String hostname, String username, String password) { + restClient = new RangerRESTClient(hostname, "", new Configuration()); + + restClient.setBasicAuthInfo(username, password); + } + + public RangerClient(RangerRESTClient restClient) { + this.restClient = restClient; + } + + /* + * ServiceDef APIs + */ + public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) throws RangerServiceException { + return callAPI(CREATE_SERVICEDEF, null, serviceDef, RangerServiceDef.class); + } + + public RangerServiceDef updateServiceDef(long serviceDefId, RangerServiceDef serviceDef) throws RangerServiceException { + return callAPI(UPDATE_SERVICEDEF_BY_ID.applyUrlFormat(serviceDefId), null, serviceDef, RangerServiceDef.class); + } + + public RangerServiceDef updateServiceDef(String serviceDefName, RangerServiceDef serviceDef) throws RangerServiceException { + return callAPI(UPDATE_SERVICEDEF_BY_NAME.applyUrlFormat(serviceDefName), null, serviceDef, RangerServiceDef.class); + } + + public void deleteServiceDef(long serviceDefId) throws RangerServiceException { + callAPI(DELETE_SERVICEDEF_BY_ID.applyUrlFormat(serviceDefId), null, null, null); + } + + public void deleteServiceDef(String serviceDefName) throws RangerServiceException { + callAPI(DELETE_SERVICEDEF_BY_NAME.applyUrlFormat(serviceDefName), null, null, null); + } + + public RangerServiceDef getServiceDef(long serviceDefId) throws RangerServiceException { + return callAPI(GET_SERVICEDEF_BY_ID.applyUrlFormat(serviceDefId), null, null, RangerServiceDef.class); + } + + public RangerServiceDef getServiceDef(String serviceDefName) throws RangerServiceException { + return callAPI(GET_SERVICEDEF_BY_NAME.applyUrlFormat(serviceDefName), null, null, RangerServiceDef.class); + } + + public List<RangerServiceDef> findServiceDefs(Map<String, String> filter) throws RangerServiceException { + return callAPI(FIND_SERVICEDEFS, filter, null, List.class); + } + + + /* + * Service APIs + */ + public RangerService createService(RangerService service) throws RangerServiceException { + return callAPI(CREATE_SERVICE, null, service, RangerService.class); + } + + public RangerService updateService(long serviceId, RangerService service) throws RangerServiceException { + return callAPI(UPDATE_SERVICE_BY_ID.applyUrlFormat(serviceId), null, service, RangerService.class); + } + + public RangerService updateService(String serviceName, RangerService service) throws RangerServiceException { + return callAPI(UPDATE_SERVICE_BY_NAME.applyUrlFormat(serviceName), null, service, RangerService.class); + } + + public void deleteService(long serviceId) throws RangerServiceException { + callAPI(DELETE_SERVICE_BY_ID.applyUrlFormat(serviceId), null, null, null); + } + + public void deleteService(String serviceName) throws RangerServiceException { + callAPI(DELETE_SERVICE_BY_NAME.applyUrlFormat(serviceName), null, null, null); + } + + public RangerService getService(long serviceId) throws RangerServiceException { + return callAPI(GET_SERVICE_BY_ID.applyUrlFormat(serviceId), null, null, RangerService.class); + } + + public RangerService getService(String serviceName) throws RangerServiceException { + return callAPI(GET_SERVICE_BY_NAME.applyUrlFormat(serviceName), null, null, RangerService.class); + } + + public List<RangerService> findServices(Map<String, String> filter) throws RangerServiceException { + return callAPI(FIND_SERVICES, filter, null, List.class); + } + + + /* + * Policy APIs + */ + public RangerPolicy createPolicy(RangerPolicy policy) throws RangerServiceException { + return callAPI(CREATE_POLICY, null, policy, RangerPolicy.class); + } + + public RangerPolicy updatePolicy(long policyId, RangerPolicy policy) throws RangerServiceException { + return callAPI(UPDATE_POLICY_BY_ID.applyUrlFormat(policyId), null, policy, RangerPolicy.class); + } + + public RangerPolicy updatePolicy(String serviceName, String policyName, RangerPolicy policy) throws RangerServiceException { + return callAPI(UPDATE_POLICY_BY_NAME.applyUrlFormat(serviceName, policyName), null, policy, RangerPolicy.class); + } + + public RangerPolicy applyPolicy(RangerPolicy policy) throws RangerServiceException { + return callAPI(APPLY_POLICY, null, policy, RangerPolicy.class); + } + + public void deletePolicy(long policyId) throws RangerServiceException { + callAPI(DELETE_POLICY_BY_ID.applyUrlFormat(policyId), null, null, null); + } + + public void deletePolicy(String serviceName, String policyName) throws RangerServiceException { + Map<String,String> queryParams = new HashMap<>(); + + queryParams.put(PARAM_POLICY_NAME, policyName); + queryParams.put("servicename", serviceName); + + callAPI(DELETE_POLICY_BY_NAME, queryParams, null, null); + } + + public RangerPolicy getPolicy(long policyId) throws RangerServiceException { + return callAPI(GET_POLICY_BY_ID.applyUrlFormat(policyId), null, null, RangerPolicy.class); + } + + public RangerPolicy getPolicy(String serviceName, String policyName) throws RangerServiceException { + return callAPI(GET_POLICY_BY_NAME.applyUrlFormat(serviceName, policyName), null, null, RangerPolicy.class); + } + + public List<RangerPolicy> getPoliciesInService(String serviceName) throws RangerServiceException { + return callAPI(GET_POLICIES_IN_SERVICE.applyUrlFormat(serviceName), null, null, List.class); + } + + public List<RangerPolicy> findPolicies(Map<String, String> filter) throws RangerServiceException { + return callAPI(FIND_POLICIES, filter, null, List.class); + } + + + /* + * SecurityZone APIs + */ + public RangerSecurityZone createSecurityZone(RangerSecurityZone securityZone) throws RangerServiceException { + return callAPI(CREATE_ZONE, null, securityZone, RangerSecurityZone.class); + } + + public RangerSecurityZone updateSecurityZone(long zoneId, RangerSecurityZone securityZone) throws RangerServiceException { + return callAPI(UPDATE_ZONE_BY_ID.applyUrlFormat(zoneId), null, securityZone, RangerSecurityZone.class); + } + + public RangerSecurityZone updateSecurityZone(String zoneName, RangerSecurityZone securityZone) throws RangerServiceException { + return callAPI(UPDATE_ZONE_BY_NAME.applyUrlFormat(zoneName), null, securityZone, RangerSecurityZone.class); + } + + public void deleteSecurityZone(long zoneId) throws RangerServiceException { + callAPI(DELETE_ZONE_BY_ID.applyUrlFormat(zoneId), null, null, null); + } + + public void deleteSecurityZone(String zoneName) throws RangerServiceException { + callAPI(DELETE_ZONE_BY_NAME.applyUrlFormat(zoneName), null, null, null); + } + + public RangerSecurityZone getSecurityZone(long zoneId) throws RangerServiceException { + return callAPI(GET_ZONE_BY_ID.applyUrlFormat(zoneId), null, null, RangerSecurityZone.class); + } + + public RangerSecurityZone getSecurityZone(String zoneName) throws RangerServiceException { + return callAPI(GET_ZONE_BY_NAME.applyUrlFormat(zoneName), null, null, RangerSecurityZone.class); + } + + public List<RangerSecurityZone> findSecurityZones(Map<String, String> filter) throws RangerServiceException { + return callAPI(FIND_ZONES, filter, null, List.class); + } + + /* + * Role APIs + */ + public RangerRole createRole(String serviceName, RangerRole role) throws RangerServiceException { + return callAPI(CREATE_ROLE, Collections.singletonMap(PARAM_SERVICE_NAME, serviceName), role, RangerRole.class); + } + + public RangerRole updateRole(long roleId, RangerRole role) throws RangerServiceException { + return callAPI(UPDATE_ROLE_BY_ID.applyUrlFormat(roleId), null, role, RangerRole.class); + } + + public void deleteRole(long roleId) throws RangerServiceException { + callAPI(DELETE_ROLE_BY_ID.applyUrlFormat(roleId), null, null, null); + } + + public void deleteRole(String roleName, String execUser, String serviceName) throws RangerServiceException { + Map<String,String> queryParams = new HashMap<>(); + + queryParams.put(PARAM_EXEC_USER, execUser); + queryParams.put(PARAM_SERVICE_NAME, serviceName); + + callAPI(DELETE_ROLE_BY_NAME.applyUrlFormat(roleName), queryParams, null, null); + } + + public RangerRole getRole(long roleId) throws RangerServiceException { + return callAPI(GET_ROLE_BY_ID.applyUrlFormat(roleId), null, null, RangerRole.class); + } + + public RangerRole getRole(String roleName, String execUser, String serviceName) throws RangerServiceException { + Map<String,String> queryParams = new HashMap<>(); + + queryParams.put(PARAM_EXEC_USER, execUser); + queryParams.put(PARAM_SERVICE_NAME, serviceName); + + return callAPI(GET_ROLE_BY_NAME.applyUrlFormat(roleName), queryParams, null, RangerRole.class); + } + + public List<String> getAllRoleNames(String execUser, String serviceName) throws RangerServiceException { + Map<String,String> queryParams = new HashMap<>(); + + queryParams.put(PARAM_EXEC_USER, execUser); + queryParams.put(PARAM_SERVICE_NAME, serviceName); + + return callAPI(GET_ALL_ROLE_NAMES.applyUrlFormat(serviceName), queryParams, null, List.class); + } + + public List<String> getUserRoles(String user) throws RangerServiceException { + return callAPI(GET_USER_ROLES.applyUrlFormat(user), null, null, List.class); + } + + public List<RangerRole> findRoles(Map<String, String> filter) throws RangerServiceException { + return callAPI(FIND_ROLES, filter, null, List.class); + } + + public RESTResponse grantRole(String serviceName, GrantRevokeRoleRequest request) throws RangerServiceException { + return callAPI(GRANT_ROLE.applyUrlFormat(serviceName), null, request, RESTResponse.class); + } + + public RESTResponse revokeRole(String serviceName, GrantRevokeRoleRequest request) throws RangerServiceException { + return callAPI(REVOKE_ROLE.applyUrlFormat(serviceName), null, request, RESTResponse.class); + } + + + /* + * Admin APIs + */ + public List<RangerPluginInfo> getPluginsInfo() throws RangerServiceException { + return callAPI(GET_PLUGIN_INFO, null, null, List.class); + } + + public void deletePolicyDeltas(int days, boolean reloadServicePoliciesCache) throws RangerServiceException { + Map<String,String> queryParams = new HashMap<>(); + + queryParams.put(PARAM_DAYS, String.valueOf(days)); + queryParams.put(PARAM_RELOAD_SERVICE_POLICIES_CACHE, String.valueOf(reloadServicePoliciesCache)); + + callAPI(DELETE_POLICY_DELTAS, queryParams, null, null); + } + + + private <T> T callAPI(API api, Map<String, String> params, Object request, Class<T> responseType) throws RangerServiceException { + T ret = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> callAPI({},{},{},{})",api, params, request, responseType); + LOG.debug("------------------------------------------------------"); + LOG.debug("Call : {} {}", api.getMethod(), api.getNormalizedPath()); + LOG.debug("Content-type : {} ", api.getConsumes()); + LOG.debug("Accept : {} ", api.getProduces()); + if (request != null) { + LOG.debug("Request : {}", request); + } + } + + final ClientResponse clientResponse; + + try { + switch (api.getMethod()) { + case HttpMethod.POST: + clientResponse = restClient.post(api.getPath(), params, request); + break; + + case HttpMethod.PUT: + clientResponse = restClient.put(api.getPath(), params, request); + break; + + case HttpMethod.GET: + clientResponse = restClient.get(api.getPath(), params); + break; + + case HttpMethod.DELETE: + clientResponse = restClient.delete(api.getPath(), params); + break; + + default: + LOG.error(api.getMethod() + ": unsupported HTTP method"); + + clientResponse = null; + } + } catch (Exception excp) { + throw new RangerServiceException(excp); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("method={}, path={}, contentType={}, accept={}, httpStatus={}", api.getMethod(), api.getNormalizedPath(), api.getConsumes(), api.getProduces(), (clientResponse != null ? clientResponse.getStatus() : "null")); + } + + if (clientResponse == null) { + throw new RangerServiceException(api, clientResponse); + } else if (clientResponse.getStatus() == api.getExpectedStatus().getStatusCode()) { + if (responseType != null) { + ret = clientResponse.getEntity(responseType); + + if (LOG.isDebugEnabled()) { + LOG.debug("Response: {}", restClient.toJson(ret)); + LOG.debug("------------------------------------------------------"); + } + } + } else if (clientResponse.getStatus() == ClientResponse.Status.SERVICE_UNAVAILABLE.getStatusCode()) { + LOG.error("Ranger Admin unavailable. HTTP Status: {}", clientResponse.getStatus()); + } else { + throw new RangerServiceException(api, clientResponse); + } + + if(LOG.isDebugEnabled()){ + LOG.debug("<== callAPI({},{},{},{}), result = {}", api, params, request, responseType, ret); + } + return ret; + } + + public static class API { + private static final Logger LOG = LoggerFactory.getLogger(API.class); + + private final String path; + private final String method; + private final Response.Status expectedStatus; + private final String consumes; + private final String produces; + + + public API(String path, String method, Response.Status expectedStatus) { + this(path, method, expectedStatus, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON); + } + + public API(String path, String method, Response.Status expectedStatus, String consumes, String produces) { + this.path = path; + this.method = method; + this.expectedStatus = expectedStatus; + this.consumes = consumes; + this.produces = produces; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } + + public Response.Status getExpectedStatus() { + return expectedStatus; + } + + public String getConsumes() { + return consumes; + } + + public String getProduces() { + return produces; + } + + public String getNormalizedPath() { + // This method used to return Paths.get(path).normalize().toString(), but + // the use of Paths.get(path) on Windows produces a path with Windows + // path separators (i.e. back-slashes) which is not valid for a URI + // and will result in an HTTP 404 status code. + String ret = null; + + try { + URI uri = new URI(path); + + if (uri != null) { + URI normalizedUri = uri.normalize(); + + ret = normalizedUri.toString(); + } + } catch (Exception e) { + LOG.error("getNormalizedPath() caught exception for path={}", path, e); + + ret = null; + } + + return ret; + } + + public API applyUrlFormat(Object... params) throws RangerServiceException { + try{ + return new API(String.format(path, params), method, expectedStatus, consumes, produces); + } catch(IllegalFormatException e) { + LOG.error("Arguments not formatted properly"); + + throw new RangerServiceException(e); + } + } + } +} \ No newline at end of file diff --git a/intg/src/main/java/org/apache/ranger/RangerServiceException.java b/intg/src/main/java/org/apache/ranger/RangerServiceException.java new file mode 100644 index 0000000..9b909a4 --- /dev/null +++ b/intg/src/main/java/org/apache/ranger/RangerServiceException.java @@ -0,0 +1,44 @@ +/* + * 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; + +import com.sun.jersey.api.client.ClientResponse; + +public class RangerServiceException extends Exception { + private final ClientResponse.Status status; + + public RangerServiceException(Exception e) { + super(e); + + this.status = null; + } + + public RangerServiceException(RangerClient.API api, ClientResponse response) { + this(api, response == null ? null : ClientResponse.Status.fromStatusCode(response.getStatus()), response == null ? null : response.getEntity(String.class)); + } + + private RangerServiceException(RangerClient.API api, ClientResponse.Status status, String response) { + super("Ranger API " + api + " failed: statusCode=" + (status != null ? status.getStatusCode() : "null") + + ", status=" + status + ", response:" + response); + + this.status = status; + } + + public ClientResponse.Status getStatus() { return status; } +} diff --git a/intg/src/main/resources/log4j.properties b/intg/src/main/resources/log4j.properties new file mode 100644 index 0000000..9c8bd00 --- /dev/null +++ b/intg/src/main/resources/log4j.properties @@ -0,0 +1,23 @@ +# +# 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. +# +log4j.rootLogger = INFO,console +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=INFO +log4j.appender.console.Target=System.out +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %m%n \ No newline at end of file diff --git a/intg/src/test/java/org/apache/ranger/TestRangerClient.java b/intg/src/test/java/org/apache/ranger/TestRangerClient.java new file mode 100644 index 0000000..08e1b38 --- /dev/null +++ b/intg/src/test/java/org/apache/ranger/TestRangerClient.java @@ -0,0 +1,150 @@ +/* + * 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; + +import com.sun.jersey.api.client.ClientResponse; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.util.RangerRESTClient; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.*; +import org.mockito.junit.MockitoJUnitRunner; +import org.testng.annotations.BeforeMethod; + +import java.util.*; + +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.Response; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class TestRangerClient { + private static final RangerClient.API GET_TEST_API = new RangerClient.API("/relative/path/test", HttpMethod.GET, Response.Status.OK); + + + @BeforeMethod + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void apiGet_Success() throws Exception { + try { + RangerRESTClient restClient = mock(RangerRESTClient.class); + ClientResponse response = mock(ClientResponse.class); + RangerClient client = new RangerClient(restClient); + RangerService service = new RangerService("testType", "testService", "MockedService", "testTag", new HashMap<>()); + + when(restClient.get(anyString(), any())).thenReturn(response); + when(response.getStatus()).thenReturn(GET_TEST_API.getExpectedStatus().getStatusCode()); + when(response.getEntity(RangerService.class)).thenReturn(service); + + RangerService ret = client.getService(service.getName()); + + Assert.assertNotNull(ret); + Assert.assertEquals(ret.getName(), service.getName()); + } catch(RangerServiceException excp){ + Assert.fail("Not expected to fail! Found exception: " + excp); + } + } + + @Test + public void apiGet_ServiceUnavailable() throws Exception { + try { + RangerRESTClient restClient = mock(RangerRESTClient.class); + ClientResponse response = mock(ClientResponse.class); + RangerClient client = new RangerClient(restClient); + + when(restClient.get(anyString(), any())).thenReturn(response); + when(response.getStatus()).thenReturn(ClientResponse.Status.SERVICE_UNAVAILABLE.getStatusCode()); + + RangerService ret = client.getService(1L); + + Assert.assertNull(ret); + } catch(RangerServiceException excp){ + Assert.fail("Not expected to fail! Found exception: " + excp); + } + } + + @Test + public void apiGet_FailWithUnexpectedStatusCode() throws Exception { + try { + RangerRESTClient restClient = mock(RangerRESTClient.class); + ClientResponse response = mock(ClientResponse.class); + RangerClient client = new RangerClient(restClient); + + when(restClient.get(anyString(), any())).thenReturn(response); + when(response.getStatus()).thenReturn(ClientResponse.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + + client.getService(1L); + + Assert.fail("supposed to fail with RangerServiceException"); + } catch(RangerServiceException excp) { + Assert.assertTrue(excp.getMessage().contains("statusCode=" + ClientResponse.Status.INTERNAL_SERVER_ERROR.getStatusCode())); + Assert.assertTrue(excp.getMessage().contains("status=" + ClientResponse.Status.INTERNAL_SERVER_ERROR.getReasonPhrase())); + } + } + + @Test + public void apiGet_FailWithNullResponse() throws Exception { + try { + RangerRESTClient restClient = mock(RangerRESTClient.class); + RangerClient client = new RangerClient(restClient); + + when(restClient.get(anyString(), any())).thenReturn(null); + + client.getService(1L); + + Assert.fail("supposed to fail with RangerServiceException"); + } catch(RangerServiceException excp) { + Assert.assertTrue(excp.getMessage().contains("statusCode=null")); + Assert.assertTrue(excp.getMessage().contains("status=null")); + } + } + + @Test + public void api_UrlMissingFormat() { + try { + new RangerClient.API("%dtest%dpath%d", HttpMethod.GET, Response.Status.OK).applyUrlFormat(1,1); + Assert.fail("supposed to fail with RangerServiceException"); + } catch(RangerServiceException exp){ + Assert.assertTrue(exp.getMessage().contains("MissingFormatArgumentException")); + } + } + + @Test + public void api_UrlIllegalFormatConversion() { + try { + new RangerClient.API("testpath%d", HttpMethod.GET, Response.Status.OK).applyUrlFormat("1"); + Assert.fail("supposed to fail with RangerServiceException"); + } catch(RangerServiceException exp){ + Assert.assertTrue(exp.getMessage().contains("IllegalFormatConversionException")); + } + + try { + new RangerClient.API("testpath%f", HttpMethod.GET, Response.Status.OK).applyUrlFormat(1); + Assert.fail("supposed to fail with RangerServiceException"); + } catch(RangerServiceException exp){ + Assert.assertTrue(exp.getMessage().contains("IllegalFormatConversionException")); + } + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index d798f6c..3e97f0a 100644 --- a/pom.xml +++ b/pom.xml @@ -189,6 +189,7 @@ <storm.version>1.2.0</storm.version> <sun-jersey-bundle.version>1.19</sun-jersey-bundle.version> <tomcat.embed.version>7.0.104</tomcat.embed.version> + <testng.version>6.9.4</testng.version> <velocity.version>1.7</velocity.version> <zookeeper.version>3.4.14</zookeeper.version> <codehaus.woodstox.stax2api.version>3.1.4</codehaus.woodstox.stax2api.version> @@ -233,6 +234,7 @@ <module>agents-audit</module> <module>agents-common</module> <module>agents-cred</module> + <module>intg</module> <module>agents-installer</module> <module>credentialbuilder</module> <module>embeddedwebserver</module> @@ -289,6 +291,14 @@ </modules> </profile> <profile> + <id>ranger-examples</id> + <modules> + <module>agents-common</module> + <module>intg</module> + <module>ranger-examples</module> + </modules> + </profile> + <profile> <id>ranger-admin</id> <modules> <module>agents-common</module> @@ -600,6 +610,7 @@ <module>agents-audit</module> <module>agents-common</module> <module>agents-cred</module> + <module>intg</module> <module>agents-installer</module> <module>credentialbuilder</module> <module>embeddedwebserver</module> @@ -714,6 +725,12 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>${testng.version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-java.version}</version> diff --git a/ranger-examples/distro/pom.xml b/ranger-examples/distro/pom.xml index ce62785..91849e5 100644 --- a/ranger-examples/distro/pom.xml +++ b/ranger-examples/distro/pom.xml @@ -54,6 +54,7 @@ <descriptors> <descriptor>src/main/assembly/sampleapp.xml</descriptor> <descriptor>src/main/assembly/plugin-sampleapp.xml</descriptor> + <descriptor>src/main/assembly/sample-client.xml</descriptor> </descriptors> </configuration> </execution> @@ -68,7 +69,7 @@ <dependencies> <dependency> <groupId>org.apache.ranger</groupId> - <artifactId>ranger-sampleapp-plugin</artifactId> + <artifactId>sample-client</artifactId> <version>${project.version}</version> </dependency> </dependencies> diff --git a/ranger-examples/distro/src/main/assembly/sample-client.xml b/ranger-examples/distro/src/main/assembly/sample-client.xml new file mode 100644 index 0000000..ea915a6 --- /dev/null +++ b/ranger-examples/distro/src/main/assembly/sample-client.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<assembly> + <id>sample-client</id> + <formats> + <format>tar.gz</format> + </formats> + <baseDirectory>${project.name}-${project.version}-sample-client</baseDirectory> + <includeBaseDirectory>false</includeBaseDirectory> + <moduleSets> + <moduleSet> + <useAllReactorProjects>true</useAllReactorProjects> + <includes> + <include>org.apache.ranger:sample-client</include> + <include>org.apache.ranger:ranger-intg</include> + <include>org.apache.ranger:ranger-plugins-common</include> + </includes> + <binaries> + <outputDirectory>lib</outputDirectory> + <includeDependencies>true</includeDependencies> + <unpack>false</unpack> + <directoryMode>755</directoryMode> + <fileMode>644</fileMode> + <includes> + <include>commons-cli:commons-cli</include> + <include>commons-logging:commons-logging:jar:${commons.logging.version}</include> + <include>commons-lang:commons-lang</include> + <include>com.google.code.gson:gson</include> + <include>org.slf4j:slf4j-api:jar:${slf4j-api.version}</include> + <include>org.slf4j:slf4j-log4j12</include> + <include>log4j:log4j</include> + <include>org.apache.commons:commons-configuration2:jar:${commons.configuration.version}</include> + <include>org.apache.hadoop:hadoop-common:jar:${hadoop.version}</include> + <include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include> + <include>org.eclipse.persistence:eclipselink</include> + <include>org.eclipse.persistence:javax.persistence</include> + <include>commons-collections:commons-collections</include> + <include>com.sun.jersey:jersey-bundle</include> + <include>commons-io:commons-io</include> + <include>com.google.guava:guava:jar:${google.guava.version}</include> + <include>org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version}</include> + <include>org.noggit:noggit:jar:${noggit.version}</include> + <include>org.codehaus.jackson:jackson-core-asl</include> + <include>org.codehaus.jackson:jackson-jaxrs</include> + <include>org.codehaus.jackson:jackson-mapper-asl</include> + <include>org.codehaus.jackson:jackson-xc</include> + <include>org.apache.ranger:ranger-plugins-audit</include> + <include>com.kstruct:gethostname4j:jar:${kstruct.gethostname4j.version}</include> + <include>net.java.dev.jna:jna:jar:${jna.version}</include> + <include>net.java.dev.jna:jna-platform:jar:${jna-platform.version}</include> + <include>com.fasterxml.woodstox:woodstox-core:jar:${fasterxml.woodstox.version}</include> + <include>org.codehaus.woodstox:stax2-api:jar:${codehaus.woodstox.stax2api.version}</include> + </includes> + </binaries> + </moduleSet> + </moduleSets> + + <fileSets> + <fileSet> + <outputDirectory></outputDirectory> + <directory>${project.parent.basedir}/sample-client/scripts</directory> + <includes> + <include>*.sh</include> + </includes> + <fileMode>755</fileMode> + </fileSet> + <fileSet> + <directoryMode>755</directoryMode> + <fileMode>644</fileMode> + <outputDirectory>lib</outputDirectory> + <directory>../sample-client/src/main/resources</directory> + <includes> + <include>*.properties</include> + </includes> + </fileSet> + </fileSets> +</assembly> diff --git a/ranger-examples/pom.xml b/ranger-examples/pom.xml index b3ceed4..ed35be8 100644 --- a/ranger-examples/pom.xml +++ b/ranger-examples/pom.xml @@ -29,5 +29,6 @@ <module>sampleapp</module> <module>plugin-sampleapp</module> <module>distro</module> + <module>sample-client</module> </modules> </project> diff --git a/ranger-examples/sample-client/pom.xml b/ranger-examples/sample-client/pom.xml new file mode 100644 index 0000000..1e205a4 --- /dev/null +++ b/ranger-examples/sample-client/pom.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>ranger-examples</artifactId> + <groupId>org.apache.ranger</groupId> + <version>2.1.0-SNAPSHOT</version> + </parent> + <packaging>jar</packaging> + <modelVersion>4.0.0</modelVersion> + + <artifactId>sample-client</artifactId> + <dependencies> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-intg</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-plugins-common</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>commons-cli</groupId> + <artifactId>commons-cli</artifactId> + <version>${commons.cli.version}</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>${google.guava.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j-api.version}</version> + </dependency> + </dependencies> +</project> \ No newline at end of file diff --git a/ranger-examples/sample-client/scripts/run-sample-client.sh b/ranger-examples/sample-client/scripts/run-sample-client.sh new file mode 100644 index 0000000..2260476 --- /dev/null +++ b/ranger-examples/sample-client/scripts/run-sample-client.sh @@ -0,0 +1,50 @@ +#!/bin/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. + +usage() { + echo "usage: run-sample-client.sh + -n <arg> Hostname to connect to + -h show help." + exit 1 +} +JARS= + for i in lib/*.jar +do + JARS="${JARS}:$i" +done +JAVA_CMD="java -Dlog4j.configuration=file:lib/log4j.properties -cp ${JARS} org.apache.ranger.examples.sampleclient.SampleClient" +while getopts "n:h" opt; do + case $opt in + n) HOST=$OPTARG + JAVA_CMD="$JAVA_CMD -h $HOST" + ;; + h) usage + ;; + \?) echo -e \\n"Option -$OPTARG not allowed." + usage + ;; + esac +done + +prompt="Sample Authentication User Name:" +read -p "$prompt" userName +prompt="Sample Authentication User Password:" +read -p "$prompt" -s password +printf "\n" +JAVA_CMD="$JAVA_CMD -u $userName -p $password" +printf "Java command : $JAVA_CMD\n" +$JAVA_CMD \ No newline at end of file diff --git a/ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/sampleclient/SampleClient.java b/ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/sampleclient/SampleClient.java new file mode 100644 index 0000000..b6ab313 --- /dev/null +++ b/ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/sampleclient/SampleClient.java @@ -0,0 +1,193 @@ +/* + * 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.examples.sampleclient; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.cli.*; +import org.apache.ranger.RangerClient; +import org.apache.ranger.RangerServiceException; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerRole; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class SampleClient { + private static final Logger LOG = LoggerFactory.getLogger(SampleClient.class); + + + @SuppressWarnings("static-access") + public static void main(String[] args) throws RangerServiceException { + Gson gsonBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").setPrettyPrinting().create(); + Options options = new Options(); + + Option host = OptionBuilder.hasArgs(1).isRequired().withLongOpt("host").withDescription("hostname").create('h'); + Option user = OptionBuilder.hasArgs(1).isRequired().withLongOpt("user").withDescription("username").create('u'); + Option pass = OptionBuilder.hasArgs(1).isRequired().withLongOpt("pass").withDescription("password").create('p'); + + options.addOption(host); + options.addOption(user); + options.addOption(pass); + + CommandLineParser parser = new BasicParser(); + CommandLine cmd; + + try { + cmd = parser.parse(options, args); + } catch (ParseException e) { + throw new RuntimeException(e); + } + + String hostName = cmd.getOptionValue('h'); + String userName = cmd.getOptionValue('u'); + String password = cmd.getOptionValue('p'); + + RangerClient rangerClient = new RangerClient(hostName, userName, password); + + String serviceDefName = "sampleServiceDef"; + String serviceName = "sampleService"; + String policyName = "samplePolicy"; + String roleName = "sampleRole"; + Map<String,String> filter = Collections.emptyMap(); + + + /* + Create a new Service Definition + */ + + RangerServiceDef.RangerServiceConfigDef config = new RangerServiceDef.RangerServiceConfigDef(); + config.setItemId(1L); + config.setName("sampleConfig"); + config.setType("string"); + List<RangerServiceDef.RangerServiceConfigDef> configs = Collections.singletonList(config); + + RangerServiceDef.RangerAccessTypeDef accessType = new RangerServiceDef.RangerAccessTypeDef(); + accessType.setItemId(1L); + accessType.setName("sampleAccess"); + List<RangerServiceDef.RangerAccessTypeDef> accessTypes = Collections.singletonList(accessType); + + RangerServiceDef.RangerResourceDef resourceDef = new RangerServiceDef.RangerResourceDef(); + resourceDef.setItemId(1L); + resourceDef.setName("root"); + resourceDef.setType("string"); + List<RangerServiceDef.RangerResourceDef> resourceDefs = Collections.singletonList(resourceDef); + + RangerServiceDef serviceDef = new RangerServiceDef(); + serviceDef.setName(serviceDefName); + serviceDef.setConfigs(configs); + serviceDef.setAccessTypes(accessTypes); + serviceDef.setResources(resourceDefs); + + RangerServiceDef createdServiceDef = rangerClient.createServiceDef(serviceDef); + LOG.info("New Service Definition created successfully {}", gsonBuilder.toJson(createdServiceDef)); + + /* + Create a new Service + */ + RangerService service = new RangerService(); + service.setType(serviceDefName); + service.setName(serviceName); + + RangerService createdService = rangerClient.createService(service); + LOG.info("New Service created successfully {}", gsonBuilder.toJson(createdService)); + + /* + Policy Management + */ + + + /* + Create a new Policy + */ + Map<String, RangerPolicy.RangerPolicyResource> resource = Collections.singletonMap( + "root", new RangerPolicy.RangerPolicyResource(Collections.singletonList("/path/to/sample/resource"),false,false)); + RangerPolicy policy = new RangerPolicy(); + policy.setService(serviceName); + policy.setName(policyName); + policy.setResources(resource); + + RangerPolicy createdPolicy = rangerClient.createPolicy(policy); + LOG.info("New Policy created successfully {}", gsonBuilder.toJson(createdPolicy)); + + /* + Get a policy by name + */ + RangerPolicy fetchedPolicy = rangerClient.getPolicy(serviceName, policyName); + LOG.info("Policy: {} fetched {}", policyName, gsonBuilder.toJson(fetchedPolicy)); + + + /* + Delete a policy + */ + rangerClient.deletePolicy(serviceName, policyName); + LOG.info("Policy {} successfully deleted", policyName); + + + /* + Delete a Service + */ + rangerClient.deleteService(serviceName); + LOG.info("Service {} successfully deleted", serviceName); + + + /* + Delete a Service Definition + */ + rangerClient.deleteServiceDef(serviceDefName); + LOG.info("Service Definition {} successfully deleted", serviceDefName); + + + /* + Role Management + */ + + /* + Create a role in Ranger + */ + RangerRole sampleRole = new RangerRole(); + sampleRole.setName(roleName); + sampleRole.setDescription("Sample Role"); + sampleRole.setUsers(Collections.singletonList(new RangerRole.RoleMember(null,true))); + sampleRole = rangerClient.createRole(serviceName, sampleRole); + LOG.info("New Role successfully created {}", gsonBuilder.toJson(sampleRole)); + + /* + Update a role in Ranger + */ + sampleRole.setDescription("Updated Sample Role"); + RangerRole updatedRole = rangerClient.updateRole(sampleRole.getId(), sampleRole); + LOG.info("Role {} successfully updated {}", roleName, gsonBuilder.toJson(updatedRole)); + + /* + Get all roles in Ranger + */ + List<RangerRole> allRoles = rangerClient.findRoles(filter); + LOG.info("List of Roles {}", gsonBuilder.toJson(allRoles)); + + /* + Delete a role in Ranger + */ + rangerClient.deleteRole(roleName, userName, serviceName); + LOG.info("Role {} successfully deleted", roleName); + } +} diff --git a/ranger-examples/sample-client/src/main/resources/log4j.properties b/ranger-examples/sample-client/src/main/resources/log4j.properties new file mode 100644 index 0000000..9c8bd00 --- /dev/null +++ b/ranger-examples/sample-client/src/main/resources/log4j.properties @@ -0,0 +1,23 @@ +# +# 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. +# +log4j.rootLogger = INFO,console +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=INFO +log4j.appender.console.Target=System.out +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %m%n \ No newline at end of file