You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by ad...@apache.org on 2017/01/18 18:58:44 UTC
[1/4] incubator-hawq git commit: HAWQ-1203. Ranger Plugin Service
Implementation. (with contributions by Lav Jain and Leslie Chang) (close
#1092)
Repository: incubator-hawq
Updated Branches:
refs/heads/master e46f06cc9 -> 7f36b35bd
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java
new file mode 100644
index 0000000..0a439db
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java
@@ -0,0 +1,325 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+import org.apache.hawq.ranger.authorization.model.HawqPrivilege;
+import org.apache.hawq.ranger.authorization.model.HawqResource;
+import org.apache.hawq.ranger.authorization.model.ResourceAccess;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.internal.util.collections.Sets;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class RangerHawqAuthorizerTest {
+
+ private static final Integer TEST_REQUEST_ID = 1;
+ private static final String TEST_USER = "alex";
+ private static final String TEST_CLIENT = "1.2.3.4";
+ private static final String TEST_CONTEXT = "SELECT * FROM sales";
+ private static final Set<HawqPrivilege> TEST_PRIVILEGES = Sets.newSet(HawqPrivilege.select, HawqPrivilege.update);
+
+ private static final String TEST_RESOURCE_REQUEST =
+ "finance:us:sales>select,update#finance:emea:sales>create";
+ private static final String TEST_RESOURCE_RESPONSE_ALL_FALSE =
+ "finance:us:sales>select,update>false#finance:emea:sales>create>false";
+ private static final String TEST_RESOURCE_RESPONSE_ALL_TRUE =
+ "finance:us:sales>select,update>true#finance:emea:sales>create>true";
+ private static final String TEST_RESOURCE_RESPONSE_US_ALLOWED_EMEA_DENIED =
+ "finance:us:sales>select,update>true#finance:emea:sales>create>false";
+ private static final String TEST_RESOURCE_RESPONSE_UPDATE_DENIED =
+ "finance:us:sales>select,update>false#finance:emea:sales>create>true";
+
+ private static final String TEST_RESOURCE_REQUEST_CREATE_SCHEMA = "finance>create";
+ private static final String TEST_RESOURCE_RESPONSE_CREATE_SCHEMA = "finance>create>true";
+ private static final String TEST_RESOURCE_REQUEST_USAGE_SCHEMA = "finance:us>usage";
+ private static final String TEST_RESOURCE_RESPONSE_USAGE_SCHEMA = "finance:us>usage>true";
+
+ private RangerHawqAuthorizer authorizer;
+
+ @Mock
+ private RangerBasePlugin mockRangerPlugin;
+ @Mock
+ private RangerAccessResult mockRangerAccessResult;
+
+ @Before
+ public void setup() throws Exception {
+ authorizer = RangerHawqAuthorizer.getInstance();
+ authorizer.setRangerPlugin(mockRangerPlugin);
+ }
+
+ @Test
+ public void testAuthorize_allAllowed() throws Exception {
+ when(mockRangerPlugin.isAccessAllowed(any(RangerAccessRequest.class))).thenReturn(mockRangerAccessResult);
+ when(mockRangerAccessResult.getIsAllowed()).thenReturn(true);
+ testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_ALL_TRUE);
+ }
+
+ @Test
+ public void testAuthorize_allDenied() throws Exception {
+ when(mockRangerPlugin.isAccessAllowed(any(RangerAccessRequest.class))).thenReturn(mockRangerAccessResult);
+ when(mockRangerAccessResult.getIsAllowed()).thenReturn(false);
+ testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_ALL_FALSE);
+ }
+
+ @Test
+ public void testAuthorize_usAllowedEmeaDenied() throws Exception {
+ RangerAccessResult mockRangerAccessResultUS = mock(RangerAccessResult.class);
+ RangerAccessResult mockRangerAccessResultEMEA = mock(RangerAccessResult.class);
+
+ when(mockRangerPlugin.isAccessAllowed(argThat(new SchemaMatcher("us")))).thenReturn(mockRangerAccessResultUS);
+ when(mockRangerPlugin.isAccessAllowed(argThat(new SchemaMatcher("emea")))).thenReturn(mockRangerAccessResultEMEA);
+ when(mockRangerAccessResultUS.getIsAllowed()).thenReturn(true);
+ when(mockRangerAccessResultEMEA.getIsAllowed()).thenReturn(false);
+ testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_US_ALLOWED_EMEA_DENIED);
+ }
+
+ @Test
+ public void testAuthorize_partialPrivilegeUpdateDenied() throws Exception {
+ RangerAccessResult mockRangerAccessResultCreateSelect = mock(RangerAccessResult.class);
+ RangerAccessResult mockRangerAccessResultUpdate = mock(RangerAccessResult.class);
+
+ when(mockRangerPlugin.isAccessAllowed(argThat(new PrivilegeMatcher("create", "select")))).thenReturn(mockRangerAccessResultCreateSelect);
+ when(mockRangerPlugin.isAccessAllowed(argThat(new PrivilegeMatcher("update")))).thenReturn(mockRangerAccessResultUpdate);
+ when(mockRangerAccessResultCreateSelect.getIsAllowed()).thenReturn(true);
+ when(mockRangerAccessResultUpdate.getIsAllowed()).thenReturn(false);
+ testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_UPDATE_DENIED);
+ }
+
+ @Test
+ public void testAuthorize_createSchemaAllowed() throws Exception {
+ RangerAccessResult mockRangerAccessResultCreate = mock(RangerAccessResult.class);
+
+ when(mockRangerPlugin.isAccessAllowed(argThat(new PrivilegeMatcher("create-schema")))).thenReturn(mockRangerAccessResultCreate);
+ when(mockRangerAccessResultCreate.getIsAllowed()).thenReturn(true);
+ testRequest(TEST_RESOURCE_REQUEST_CREATE_SCHEMA, TEST_RESOURCE_RESPONSE_CREATE_SCHEMA);
+ }
+
+ @Test
+ public void testAuthorize_usageSchemaAllowed() throws Exception {
+ RangerAccessResult mockRangerAccessResultUsage = mock(RangerAccessResult.class);
+
+ when(mockRangerPlugin.isAccessAllowed(argThat(new PrivilegeMatcher("usage-schema")))).thenReturn(mockRangerAccessResultUsage);
+ when(mockRangerAccessResultUsage.getIsAllowed()).thenReturn(true);
+ testRequest(TEST_RESOURCE_REQUEST_USAGE_SCHEMA, TEST_RESOURCE_RESPONSE_USAGE_SCHEMA);
+ }
+
+ /* ----- VALIDATION TESTS ----- */
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_requestId() {
+ AuthorizationRequest request = prepareRequest(null, TEST_USER, TEST_CLIENT, TEST_CONTEXT, TEST_RESOURCE_REQUEST);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_user() {
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, "", TEST_CLIENT, TEST_CONTEXT, TEST_RESOURCE_REQUEST);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_client() {
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, "", TEST_CONTEXT, TEST_RESOURCE_REQUEST);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_context() {
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, "", TEST_RESOURCE_REQUEST);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_emptyAccessSet() {
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, TEST_CONTEXT, new HashSet<ResourceAccess>());
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_emptyResource() {
+ ResourceAccess resourceAccess = new ResourceAccess();
+ resourceAccess.setResource(new HashMap<HawqResource, String>());
+ resourceAccess.setPrivileges(TEST_PRIVILEGES);
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, TEST_CONTEXT, resourceAccess);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_emptyResourceValue() {
+ ResourceAccess resourceAccess = new ResourceAccess();
+ HashMap<HawqResource, String> resource = new HashMap<>();
+ resource.put(HawqResource.database, "");
+ resourceAccess.setResource(resource);
+ resourceAccess.setPrivileges(TEST_PRIVILEGES);
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, TEST_CONTEXT, resourceAccess);
+ authorizer.isAccessAllowed(request);
+ }
+ @Test(expected=IllegalArgumentException.class)
+ public void testAuthorize_validationFailure_emptyPrivileges() {
+ ResourceAccess resourceAccess = new ResourceAccess();
+ HashMap<HawqResource, String> resource = new HashMap<>();
+ resource.put(HawqResource.database, "abc");
+ resourceAccess.setResource(resource);
+ resourceAccess.setPrivileges(new HashSet<HawqPrivilege>());
+ AuthorizationRequest request = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, TEST_CONTEXT, resourceAccess);
+ authorizer.isAccessAllowed(request);
+ }
+
+ /* ----- HELPER METHODS ----- */
+
+ private void testRequest(String request, String expectedResponse) {
+ AuthorizationRequest authRequest = prepareRequest(TEST_REQUEST_ID, TEST_USER, TEST_CLIENT, TEST_CONTEXT, request);
+ AuthorizationResponse authResponse = authorizer.isAccessAllowed(authRequest);
+ validateResponse(authResponse, expectedResponse);
+ }
+
+ private AuthorizationRequest prepareRequest(
+ Integer requestId, String user, String clientIp, String context, Set<ResourceAccess> access) {
+
+ AuthorizationRequest request = new AuthorizationRequest();
+ request.setRequestId(requestId);
+ request.setUser(user);
+ request.setClientIp(clientIp);
+ request.setContext(context);
+ request.setAccess(access);
+
+ return request;
+ }
+
+ private AuthorizationRequest prepareRequest(
+ Integer requestId, String user, String clientIp, String context, ResourceAccess resourceAccess) {
+
+ Set<ResourceAccess> access = new HashSet<>();
+ access.add(resourceAccess);
+ return prepareRequest(requestId, user, clientIp, context, access);
+ }
+
+ private AuthorizationRequest prepareRequest(
+ Integer requestId, String user, String clientIp, String context, String resources) {
+
+ Set<ResourceAccess> access = new HashSet<>();
+ // resource string is like "db:schema:table>select,update#db:schema:table>create"
+ for (String resourceStr : resources.split("#")) {
+ String[] parts = resourceStr.split(">");
+ String[] resource = parts[0].split(":");
+ String[] privs = parts[1].split(",");
+
+ Map<HawqResource, String> tableResource = new HashMap<>();
+ tableResource.put(HawqResource.database, resource[0]);
+ if (resource.length > 1) {
+ tableResource.put(HawqResource.schema, resource[1]);
+ }
+ if (resource.length > 2) {
+ tableResource.put(HawqResource.table, resource[2]);
+ }
+ ResourceAccess tableAccess = new ResourceAccess();
+ tableAccess.setResource(tableResource);
+
+ Set<HawqPrivilege> privSet = new HashSet<>();
+ for (String priv : privs) {
+ privSet.add(HawqPrivilege.valueOf(priv));
+ }
+ tableAccess.setPrivileges(privSet);
+ access.add(tableAccess);
+ }
+
+ return prepareRequest(requestId, user, clientIp, context, access);
+ }
+
+ private void validateResponse(AuthorizationResponse response, String resources) {
+
+ assertNotNull(response);
+
+ Set<ResourceAccess> actual = response.getAccess();
+ Set<ResourceAccess> expected = new HashSet<>();
+
+ // resources string is like "db:schema:table>select,update>true#db:schema:table>create>false"
+ for (String resourceStr : resources.split("#")) {
+ String[] parts = resourceStr.split(">");
+ String[] resource = parts[0].split(":");
+ String[] privs = parts[1].split(",");
+ Boolean allowed = Boolean.valueOf(parts[2]);
+
+ Map<HawqResource, String> tableResource = new HashMap<>();
+ tableResource.put(HawqResource.database, resource[0]);
+ if (resource.length > 1) {
+ tableResource.put(HawqResource.schema, resource[1]);
+ }
+ if (resource.length > 2) {
+ tableResource.put(HawqResource.table, resource[2]);
+ }
+ ResourceAccess tableAccess = new ResourceAccess();
+ tableAccess.setResource(tableResource);
+
+ Set<HawqPrivilege> privSet = new HashSet<>();
+ for (String priv : privs) {
+ privSet.add(HawqPrivilege.fromString(priv));
+ }
+ tableAccess.setPrivileges(privSet);
+ tableAccess.setAllowed(allowed);
+
+ expected.add(tableAccess);
+ }
+
+ assertEquals(expected.size(), actual.size());
+ assertEquals(expected, actual);
+ }
+
+ /* ----- Argument Matchers ----- */
+
+ private class SchemaMatcher extends ArgumentMatcher<RangerAccessRequest> {
+ private String schema;
+ public SchemaMatcher(String schema) {
+ this.schema = schema;
+ }
+ @Override
+ public boolean matches(Object request) {
+ return request == null ? false :
+ schema.equals(((RangerAccessRequest) request).getResource().getAsMap().get("schema"));
+ }
+ };
+
+ private class PrivilegeMatcher extends ArgumentMatcher<RangerAccessRequest> {
+ private Set<String> privileges;
+ public PrivilegeMatcher(String... privileges) {
+ this.privileges = Sets.newSet(privileges);
+ }
+ @Override
+ public boolean matches(Object request) {
+ return request == null ? false :
+ privileges.contains(((RangerAccessRequest) request).getAccessType());
+ }
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResourceTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResourceTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResourceTest.java
new file mode 100644
index 0000000..40c2217
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResourceTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static junit.framework.TestCase.*;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(RangerHawqAuthorizer.class)
+public class RangerHawqPluginResourceTest {
+
+ private RangerHawqPluginResource resource;
+
+ @Mock
+ private RangerHawqAuthorizer mockAuthorizer;
+ @Mock
+ private AuthorizationResponse mockResponse;
+ @Mock
+ private RuntimeException mockException;
+
+ @Before
+ public void setup() throws Exception {
+ PowerMockito.mockStatic(RangerHawqAuthorizer.class);
+ when(RangerHawqAuthorizer.getInstance()).thenReturn(mockAuthorizer);
+ resource = new RangerHawqPluginResource();
+ }
+
+ @Test
+ public void testGetVersion() {
+ String version = (String) resource.version().getEntity();
+ assertEquals("{\"version\":\"version-test\"}", version);
+ }
+
+ @Test
+ public void testAuthorizeSuccess() {
+ when(mockAuthorizer.isAccessAllowed(any(AuthorizationRequest.class))).thenReturn(mockResponse);
+ AuthorizationResponse response = resource.authorize(new AuthorizationRequest());
+ assertNotNull(response);
+ assertEquals(mockResponse, response);
+ }
+
+ @Test
+ public void testAuthorizeException() {
+ when(mockAuthorizer.isAccessAllowed(any(AuthorizationRequest.class))).thenThrow(mockException);
+ try {
+ resource.authorize(new AuthorizationRequest());
+ fail("should've thrown exception");
+ } catch (Exception e) {
+ assertSame(mockException, e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapperTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapperTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapperTest.java
new file mode 100644
index 0000000..e81b76c
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapperTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ServiceExceptionMapperTest {
+
+ private ServiceExceptionMapper mapper;
+
+ @Before
+ public void setup() {
+ mapper = new ServiceExceptionMapper();
+ }
+
+ @Test
+ public void testIllegalArgumentException() {
+
+ Response response = mapper.toResponse(new IllegalArgumentException("reason"));
+ ServiceExceptionMapper.ErrorPayload entity = (ServiceExceptionMapper.ErrorPayload) response.getEntity();
+
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), entity.getStatus());
+ assertEquals("reason", entity.getMessage());
+ }
+
+ @Test
+ public void testOtherException() {
+
+ Response response = mapper.toResponse(new Exception("reason"));
+ ServiceExceptionMapper.ErrorPayload entity = (ServiceExceptionMapper.ErrorPayload) response.getEntity();
+
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), entity.getStatus());
+ assertEquals("reason", entity.getMessage());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/UtilsTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/UtilsTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/UtilsTest.java
new file mode 100644
index 0000000..bf62785
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/UtilsTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.junit.Test;
+
+import static org.apache.hawq.ranger.authorization.Utils.APP_ID_PROPERTY;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test class uses values from rps.properties file in test/resources directory.
+ */
+public class UtilsTest {
+
+ @Test
+ public void testCustomAppId_SystemEnv() throws Exception {
+ System.setProperty(APP_ID_PROPERTY, "app-id");
+ assertEquals("app-id", Utils.getAppId());
+ System.clearProperty(APP_ID_PROPERTY);
+ }
+
+ @Test
+ public void testCustomAppId_PropertyFile() throws Exception {
+ assertEquals("instance-test", Utils.getAppId());
+ }
+
+ @Test
+ public void testGetVersion() throws Exception {
+ assertEquals("version-test", Utils.getVersion());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqPrivilegeTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqPrivilegeTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqPrivilegeTest.java
new file mode 100644
index 0000000..39dd3cc
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqPrivilegeTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+public class HawqPrivilegeTest {
+
+ @Test
+ public void testSerialization() throws IOException {
+ assertEquals("create", HawqPrivilege.create.toValue());
+ assertEquals("create-schema", HawqPrivilege.create_schema.toValue());
+ assertEquals("usage-schema", HawqPrivilege.usage_schema.toValue());
+
+ ObjectMapper mapper = new ObjectMapper();
+ assertEquals("{\"value\":\"create\"}", mapper.writeValueAsString(new PrivilegeHolder(HawqPrivilege.create)));
+ assertEquals("{\"value\":\"create-schema\"}", mapper.writeValueAsString(new PrivilegeHolder(HawqPrivilege.create_schema)));
+ assertEquals("{\"value\":\"usage-schema\"}", mapper.writeValueAsString(new PrivilegeHolder(HawqPrivilege.usage_schema)));
+ }
+
+ @Test
+ public void testDeserialization() throws IOException {
+ assertNull(HawqPrivilege.fromString(null));
+ assertSame(HawqPrivilege.create, HawqPrivilege.fromString("create"));
+ assertSame(HawqPrivilege.create, HawqPrivilege.fromString("CREATE"));
+ assertSame(HawqPrivilege.create, HawqPrivilege.fromString("CreATe"));
+ assertSame(HawqPrivilege.create_schema, HawqPrivilege.fromString("CreATe-schema"));
+ assertSame(HawqPrivilege.usage_schema, HawqPrivilege.fromString("USage-schema"));
+
+
+ ObjectMapper mapper = new ObjectMapper();
+ assertSame(HawqPrivilege.create, mapper.readValue("{\"value\": \"create\"}", PrivilegeHolder.class).value);
+ assertSame(HawqPrivilege.create, mapper.readValue("{\"value\": \"CREATE\"}", PrivilegeHolder.class).value);
+ assertSame(HawqPrivilege.create, mapper.readValue("{\"value\": \"creATe\"}", PrivilegeHolder.class).value);
+ assertSame(HawqPrivilege.create_schema, mapper.readValue("{\"value\": \"CreATe-schema\"}", PrivilegeHolder.class).value);
+ assertSame(HawqPrivilege.usage_schema, mapper.readValue("{\"value\": \"USage-schema\"}", PrivilegeHolder.class).value);
+ }
+
+ public static class PrivilegeHolder {
+ public HawqPrivilege value;
+ PrivilegeHolder () {
+ }
+ PrivilegeHolder(HawqPrivilege value) {
+ this.value = value;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqResourceTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqResourceTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqResourceTest.java
new file mode 100644
index 0000000..f59a600
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/model/HawqResourceTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+public class HawqResourceTest {
+
+ @Test
+ public void testCaseInsensitiveDeserialization() throws IOException {
+ assertNull(HawqResource.fromString(null));
+ assertSame(HawqResource.database, HawqResource.fromString("database"));
+ assertSame(HawqResource.database, HawqResource.fromString("DATABASE"));
+ assertSame(HawqResource.database, HawqResource.fromString("datABAse"));
+
+ ObjectMapper mapper = new ObjectMapper();
+ assertSame(HawqResource.database, mapper.readValue("{\"value\": \"database\"}", ResourceHolder.class).value);
+ assertSame(HawqResource.database, mapper.readValue("{\"value\": \"DATABASE\"}", ResourceHolder.class).value);
+ assertSame(HawqResource.database, mapper.readValue("{\"value\": \"datABAse\"}", ResourceHolder.class).value);
+ }
+
+ public static class ResourceHolder {
+ public HawqResource value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/resources/log4j.properties b/ranger-plugin/service/src/test/resources/log4j.properties
new file mode 100644
index 0000000..b9888df
--- /dev/null
+++ b/ranger-plugin/service/src/test/resources/log4j.properties
@@ -0,0 +1,42 @@
+# 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.
+
+# see debug messages during unit tests
+#project.root.logger=DEBUG,console
+
+# suppress all logging output during unit tests
+project.root.logger=FATAL,devnull
+
+#
+# Loggers
+#
+log4j.rootLogger=${project.root.logger}
+
+# ignore most errors from the Apache Ranger and Hadoop for unit tests
+log4j.logger.org.apache.ranger=FATAL
+log4j.logger.org.apache.hadoop=FATAL
+
+#
+# Appenders
+#
+
+# nothing
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+
+# console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/resources/rps.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/resources/rps.properties b/ranger-plugin/service/src/test/resources/rps.properties
new file mode 100644
index 0000000..1fd50e5
--- /dev/null
+++ b/ranger-plugin/service/src/test/resources/rps.properties
@@ -0,0 +1,17 @@
+# 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.
+
+ranger.hawq.instance=instance-test
+version=version-test
\ No newline at end of file
[3/4] incubator-hawq git commit: HAWQ-1203. Ranger Plugin Service
Implementation. (with contributions by Lav Jain and Leslie Chang) (close
#1092)
Posted by ad...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSchemasTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSchemasTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSchemasTest.java
new file mode 100644
index 0000000..94372aa
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSchemasTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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 schema governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListSchemasTest extends LookupTestBase {
+
+ private static final Set<String> DEFAULT_SCHEMAS = Sets.newHashSet("public");
+ private static final Set<String> EAST_SCHEMAS = Sets.newHashSet("common", "japan", "public");
+ private static final Set<String> WEST_SCHEMAS = Sets.newHashSet("common", "france", "jamaica", "public");
+ private static final Set<String> ALL_SCHEMAS = Sets.newHashSet("common", "japan", "france", "jamaica", "public");
+
+ private Map<String, List<String>> resources;
+
+ @Before
+ public void setUp() {
+ resources = new HashMap<>();
+ }
+
+ @Test
+ public void testListSchema_NoResources() throws Exception {
+ resources.put("database", Arrays.asList("noschema_db"));
+ List<String> result = service.lookupResource(getContext("schema", "*", resources));
+ assertEquals(DEFAULT_SCHEMAS.size(), result.size());
+ assertEquals(DEFAULT_SCHEMAS, Sets.newHashSet(result));
+ }
+
+ @Test
+ public void testListSchemas_SingleDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("schema", "*", resources));
+ assertEquals(EAST_SCHEMAS.size(), result.size());
+ assertEquals(EAST_SCHEMAS, Sets.newHashSet(result));
+ }
+
+ @Test
+ public void testListSchemas_TwoDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("schema", "*", resources));
+ assertEquals(ALL_SCHEMAS.size(), result.size());
+ assertEquals(ALL_SCHEMAS, Sets.newHashSet(result));
+ }
+
+ @Test
+ public void testListSchemas_AllDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("schema", "*", resources));
+ assertEquals(ALL_SCHEMAS.size(), result.size());
+ assertEquals(ALL_SCHEMAS, Sets.newHashSet(result));
+ }
+
+ @Test
+ public void testListSchemas_SingleDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("schema", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSchemas_TwoDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("schema", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSchemas_AllDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("schema", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSchemas_SingleDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("schema", "ja", resources));
+ assertEquals(1, result.size());
+ assertEquals("japan", result.get(0));
+ }
+
+ @Test
+ public void testListSchemas_TwoDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("schema", "ja", resources));
+ assertEquals(2, result.size());
+ assertEquals(Sets.newHashSet("japan", "jamaica"), Sets.newHashSet(result));
+ }
+
+ @Test
+ public void testListSchemas_AllDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("schema", "ja", resources));
+ assertEquals(2, result.size());
+ assertEquals(Sets.newHashSet("japan", "jamaica"), Sets.newHashSet(result));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSequencesTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSequencesTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSequencesTest.java
new file mode 100644
index 0000000..0c601c2
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListSequencesTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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 schema governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListSequencesTest extends LookupTestBase {
+
+ private Map<String, List<String>> resources;
+
+ @Before
+ public void setUp() {
+ resources = new HashMap<>();
+ }
+
+ @Test
+ public void testListSequences_NoSchemaDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("noschema_db"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_SingleDb_SingleSchema_AllFilter_NoSequences() throws Exception {
+ resources.put("database", Arrays.asList("west"));
+ resources.put("schema", Arrays.asList("jamaica"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_SingleDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sake")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_TwoSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sprite", "sake")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sprite", "sake")));
+ }
+
+ @Test
+ public void testListSequences_TwoDb_CommonSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sprite")));
+ }
+
+ @Test
+ public void testListSequences_TwoDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sake")));
+ }
+
+ @Test
+ public void testListSequences_TwoDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sprite", "sake", "scotch")));
+ }
+
+ @Test
+ public void testListSequences_AllDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water", "sprite", "sake", "scotch")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_SingleDb_TwoSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_SingleDb_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_CommonSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_AllDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListSequences_SingleDb_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sake")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_TwoSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sprite", "sake")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sprite", "sake")));
+ }
+
+ @Test
+ public void testListSequences_SingleDb_AllSchemas_FilteredPresent2() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "w", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water")));
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_CommonSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("sequence", "w", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("water")));
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sake")));
+ }
+
+ @Test
+ public void testListSequences_TwoDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sprite", "sake", "scotch")));
+ }
+
+ @Test
+ public void testListSequences_AllDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("sequence", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sprite", "sake", "scotch")));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablesTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablesTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablesTest.java
new file mode 100644
index 0000000..1360cac
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablesTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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 schema governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListTablesTest extends LookupTestBase {
+
+ private Map<String, List<String>> resources;
+
+ @Before
+ public void setUp() {
+ resources = new HashMap<>();
+ }
+
+ @Test
+ public void testListTables_NoSchemaDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("noschema_db"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_SingleDb_SingleSchema_AllFilter_NoTables() throws Exception {
+ resources.put("database", Arrays.asList("west"));
+ resources.put("schema", Arrays.asList("jamaica"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_SingleDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "sushi")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_TwoSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "soup", "sushi")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "soup", "sushi")));
+ }
+
+ @Test
+ public void testListTables_TwoDb_CommonSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "soup")));
+ }
+
+ @Test
+ public void testListTables_TwoDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "sushi")));
+ }
+
+ @Test
+ public void testListTables_TwoDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "soup", "sushi", "stew")));
+ }
+
+ @Test
+ public void testListTables_AllDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice", "soup", "sushi", "stew")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_SingleDb_TwoSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_SingleDb_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_TwoDbs_CommonSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_TwoDbs_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_TwoDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_AllDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListTables_SingleDb_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sushi")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_TwoSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("soup", "sushi")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("soup", "sushi")));
+ }
+
+ @Test
+ public void testListTables_SingleDb_AllSchemas_FilteredPresent2() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "r", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice")));
+ }
+
+ @Test
+ public void testListTables_TwoDbs_CommonSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("table", "r", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("rice")));
+ }
+
+ @Test
+ public void testListTables_TwoDbs_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sushi")));
+ }
+
+ @Test
+ public void testListTables_TwoDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("soup", "sushi", "stew")));
+ }
+
+ @Test
+ public void testListTables_AllDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("table", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("soup", "sushi", "stew")));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablespacesTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablespacesTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablespacesTest.java
new file mode 100644
index 0000000..65048db
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListTablespacesTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListTablespacesTest extends LookupTestBase {
+
+ private static final Set<String> TABLESPACES = Sets.newHashSet("pg_default", "pg_global", "dfs_default");
+
+ @Test
+ public void testListTablespace_All() throws Exception {
+ List<String> result = service.lookupResource(getContext("tablespace", "*"));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet(TABLESPACES)));
+ }
+
+ @Test
+ public void testListTablespace_FilteredPresent() throws Exception {
+ List<String> result = service.lookupResource(getContext("tablespace", "pg_d"));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("pg_default")));
+ }
+
+ @Test
+ public void testListTablespace_FilteredAbsent() throws Exception {
+ List<String> result = service.lookupResource(getContext("tablespace", "z"));
+ assertTrue(result.isEmpty());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/LookupTestBase.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/LookupTestBase.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/LookupTestBase.java
new file mode 100644
index 0000000..25265f3
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/LookupTestBase.java
@@ -0,0 +1,65 @@
+/*
+ * 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.hawq.ranger.integration.admin;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.service.RangerServiceHawq;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.Before;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class LookupTestBase {
+
+ protected static final Log LOG = LogFactory.getLog(LookupTestBase.class);
+ protected RangerServiceHawq service;
+
+ @Before
+ public void setup() {
+ Map<String, String> configs = new HashMap<>();
+ configs = new HashMap<>();
+ configs.put("username", "gpadmin");
+ configs.put("password", "dQSF8ViAE4/I38xmFwJfCg==");
+ configs.put("hostname", "localhost");
+ configs.put("port", "5432");
+ configs.put("jdbc.driverClassName", "org.postgresql.Driver");
+
+ service = new RangerServiceHawq();
+ service.setServiceName("hawq");
+ service.setServiceType("hawq");
+ service.setConfigs(configs);
+ }
+
+ protected ResourceLookupContext getContext(String resourceName, String userInput) {
+ ResourceLookupContext context = new ResourceLookupContext();
+ context.setResourceName(resourceName);
+ context.setUserInput(userInput);
+ return context;
+ }
+
+ protected ResourceLookupContext getContext(String resourceName, String userInput, Map<String, List<String>> resources) {
+ ResourceLookupContext context = getContext(resourceName, userInput);
+ context.setResources(resources);
+ return context;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/resources/admin-tests-ddl.sql
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/resources/admin-tests-ddl.sql b/ranger-plugin/integration/admin/src/test/resources/admin-tests-ddl.sql
new file mode 100644
index 0000000..d9e7fcc
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/resources/admin-tests-ddl.sql
@@ -0,0 +1,61 @@
+-- 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.
+
+-- EAST Database and its objects
+DROP DATABASE IF EXISTS east;
+CREATE DATABASE east;
+\c east;
+CREATE SCHEMA common;
+CREATE TABLE common.rice (id integer);
+CREATE TABLE common.soup (id integer);
+CREATE SEQUENCE common.water;
+CREATE SEQUENCE common.sprite;
+CREATE FUNCTION common.eat(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE FUNCTION common.sleep(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE SCHEMA japan;
+CREATE TABLE japan.rice (id integer);
+CREATE TABLE japan.sushi (id integer);
+CREATE SEQUENCE japan.water;
+CREATE SEQUENCE japan.sake;
+CREATE FUNCTION japan.eat(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE FUNCTION japan.stand(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE LANGUAGE langdbeast HANDLER plpgsql_call_handler;
+
+-- WEST Database and its objects
+DROP DATABASE IF EXISTS west;
+CREATE DATABASE west;
+\c west;
+CREATE SCHEMA common;
+CREATE TABLE common.rice (id integer);
+CREATE TABLE common.soup (id integer);
+CREATE SEQUENCE common.water;
+CREATE SEQUENCE common.sprite;
+CREATE FUNCTION common.eat(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE FUNCTION common.sleep(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE SCHEMA france;
+CREATE TABLE france.rice (id integer);
+CREATE TABLE france.stew (id integer);
+CREATE SEQUENCE france.water;
+CREATE SEQUENCE france.scotch;
+CREATE FUNCTION france.eat(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE FUNCTION france.smile(integer) RETURNS integer AS 'select $1;' LANGUAGE SQL;
+CREATE LANGUAGE langdbwest HANDLER plpgsql_call_handler;
+CREATE SCHEMA jamaica;
+
+-- Database without an explicit schema
+DROP DATABASE IF EXISTS noschema_db;
+CREATE DATABASE noschema_db;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/resources/log4j.properties b/ranger-plugin/integration/admin/src/test/resources/log4j.properties
new file mode 100644
index 0000000..903f0b6
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+# 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.
+
+##-- To prevent junits from cluttering the build run by default all test runs send output to null appender
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+#hawq.ranger.root.logger=FATAL,devnull
+
+##-- uncomment the following line during during development/debugging so see debug messages during test run to be emitted to console
+hawq.ranger.root.logger=DEBUG,console
+log4j.rootLogger=${hawq.ranger.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/pom.xml b/ranger-plugin/integration/pom.xml
new file mode 100644
index 0000000..b6aac80
--- /dev/null
+++ b/ranger-plugin/integration/pom.xml
@@ -0,0 +1,67 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-integration</artifactId>
+ <packaging>pom</packaging>
+ <name>HAWQ Ranger Plugin - Integration Tests</name>
+ <description>HAWQ Ranger Plugin - Integration Tests</description>
+
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <modules>
+ <module>admin</module>
+ <module>service</module>
+ </modules>
+
+ <properties>
+ <jackson.version>1.9</jackson.version>
+ </properties>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/pom.xml b/ranger-plugin/integration/service/pom.xml
new file mode 100644
index 0000000..34ade8d
--- /dev/null
+++ b/ranger-plugin/integration/service/pom.xml
@@ -0,0 +1,68 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-integration-service</artifactId>
+ <packaging>jar</packaging>
+ <name>HAWQ Ranger Plugin - Integration Tests</name>
+ <description>HAWQ Ranger Plugin - Integration Tests</description>
+
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-integration</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java
new file mode 100644
index 0000000..451a289
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class DatabaseTest extends ServiceBaseTest {
+
+ private static final List<String> PRIVILEGES = Arrays.asList("connect", "temp");
+
+ public void beforeTest()
+ throws IOException {
+ createPolicy("test-database.json");
+ resources.put("database", "sirotan");
+ }
+
+ @Test
+ public void testDatabases_UserMaria_SirotanDb_Allowed()
+ throws IOException {
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testDatabases_UserMaria_DoesNotExistDb_Denied()
+ throws IOException {
+ resources.put("database", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testDatabases_UserBob_SirotanDb_Denied()
+ throws IOException {
+ assertFalse(hasAccess("bob", resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testDatabases_UserMaria_SirotanDb_Denied()
+ throws IOException {
+ deletePolicy();
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java
new file mode 100644
index 0000000..1253c38
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class FunctionTest extends ServiceBaseTest {
+
+ private static final List<String> PRIVILEGES = Arrays.asList("execute");
+
+ public void beforeTest()
+ throws IOException {
+ createPolicy("test-function.json");
+ resources.put("database", "sirotan");
+ resources.put("schema", "siroschema");
+ resources.put("function", "atan");
+ }
+
+ @Test
+ public void testFunctions_UserMaria_SirotanDb_AtanFunction_Allowed()
+ throws IOException {
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserMaria_OtherDb_AtanFunction_Denied()
+ throws IOException {
+ resources.put("database", "other");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserMaria_SirotanDb_DoesNotExistFunction_Denied()
+ throws IOException {
+ resources.put("function", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserBob_SirotanDb_AtanFunction_Denied()
+ throws IOException {
+ assertFalse(hasAccess("bob", resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserMaria_SirotanDb_AtanFunction_Denied()
+ throws IOException {
+ deletePolicy();
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserMaria_DoesNotExistDb_AtanFunction_Denied()
+ throws IOException {
+ resources.put("database", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testFunctions_UserMaria_SirotanDb_AtanFunction_Policy2_Allowed()
+ throws IOException {
+ deletePolicy();
+ createPolicy("test-function-2.json");
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java
new file mode 100644
index 0000000..6eedb08
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class LanguageTest extends ServiceBaseTest {
+
+ private static final List<String> PRIVILEGES = Arrays.asList("usage");
+
+ public void beforeTest()
+ throws IOException {
+ createPolicy("test-language.json");
+ resources.put("database", "sirotan");
+ resources.put("language", "sql");
+ }
+
+ @Test
+ public void testLanguages_UserMaria_SirotanDb_SqlLanguage_Allowed()
+ throws IOException {
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testLanguages_UserMaria_SirotanDb_DoesNotExistLanguage_Denied()
+ throws IOException {
+ resources.put("language", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testLanguages_UserBob_SirotanDb_SqlLanguage_Denied()
+ throws IOException {
+ assertFalse(hasAccess("bob", resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testLanguages_UserMaria_SirotanDb_SqlLanguage_Denied()
+ throws IOException {
+ deletePolicy();
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testLanguages_UserMaria_DoesNotExistDb_SqlLanguage_Denied()
+ throws IOException {
+ resources.put("database", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testLanguages_UserMaria_SirotanDb_SqlLanguage_Policy2_Allowed()
+ throws IOException {
+ deletePolicy();
+ createPolicy("test-language-2.json");
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java
new file mode 100644
index 0000000..f0e5c99
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ProtocolTest extends ServiceBaseTest {
+
+ private static final List<String> PRIVILEGES = Arrays.asList("select", "insert");
+
+ public void beforeTest()
+ throws IOException {
+ createPolicy("test-protocol.json");
+ resources.put("protocol", "pxf");
+ }
+
+ @Test
+ public void testProtocols_UserMaria_PxfProtocol_Allowed()
+ throws IOException {
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testProtocols_UserMaria_DoesNotExistProtocol_Denied()
+ throws IOException {
+ resources.put("protocol", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testProtocols_UserBob_PxfProtocol_Denied()
+ throws IOException {
+ assertFalse(hasAccess("bob", resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testProtocols_UserMaria_PxfProtocol_Denied()
+ throws IOException {
+ deletePolicy();
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSRequest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSRequest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSRequest.java
new file mode 100644
index 0000000..7e7787a
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSRequest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RPSRequest {
+
+ String user;
+ Map<String, String> resources;
+ List<String> privileges;
+
+ public RPSRequest(String user,
+ Map<String, String> resources,
+ List<String> privileges) {
+ this.user = user;
+ this.resources = resources;
+ this.privileges = privileges;
+ }
+
+ public String getJsonString()
+ throws IOException {
+
+ Map<String, Object> request = new HashMap<>();
+ request.put("requestId", 9);
+ request.put("user", user);
+ request.put("clientIp", "123.0.0.21");
+ request.put("context", "CREATE DATABASE sirotan;");
+ Map<String, Object> accessHash = new HashMap<>();
+ accessHash.put("resource", resources);
+ accessHash.put("privileges", privileges);
+ request.put("access", Arrays.asList(accessHash));
+ return new ObjectMapper().writeValueAsString(request);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSResponse.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSResponse.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSResponse.java
new file mode 100644
index 0000000..2ed1046
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/RPSResponse.java
@@ -0,0 +1,42 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.List;
+import java.util.Map;
+
+public class RPSResponse {
+
+ @JsonProperty
+ public int requestId;
+
+ @JsonProperty
+ public List<Map<String, Object>> access;
+
+ public List<Map<String, Object>> getAccess() {
+ return access;
+ }
+
+ public boolean hasAccess() {
+ return (boolean) access.get(0).get("allowed");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ServiceBaseTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ServiceBaseTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ServiceBaseTest.java
new file mode 100644
index 0000000..8608584
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ServiceBaseTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class ServiceBaseTest {
+
+ protected final Log log = LogFactory.getLog(this.getClass());
+
+ @Rule
+ public final TestName testName = new TestName();
+ protected final String policyName = getClass().getSimpleName();
+ protected Map<String, String> resources = new HashMap<>();
+
+ public static String RANGER_PLUGIN_SERVICE_HOST = "localhost";
+ public static String RANGER_PLUGIN_SERVICE_PORT = "8432";
+ public static String RANGER_PLUGIN_SERVICE_URL =
+ "http://" + RANGER_PLUGIN_SERVICE_HOST + ":" + RANGER_PLUGIN_SERVICE_PORT + "/rps";
+ public static String RANGER_ADMIN_HOST = "localhost";
+ public static String RANGER_ADMIN_PORT = "6080";
+ public static String RANGER_URL =
+ "http://" + RANGER_ADMIN_HOST + ":" + RANGER_ADMIN_PORT + "/service/public/v2/api";
+ public static String RANGER_TEST_USER = "maria_dev";
+ public static int POLICY_REFRESH_INTERVAL = 6000;
+
+ @Before
+ public void setUp()
+ throws IOException {
+ log.info("======================================================================================");
+ log.info("Running test " + testName.getMethodName());
+ log.info("======================================================================================");
+ beforeTest();
+ }
+
+ @After
+ public void tearDown()
+ throws IOException {
+ deletePolicy();
+ }
+
+ protected void createPolicy(String jsonFile)
+ throws IOException {
+
+ log.info("Creating policy " + policyName);
+ HttpPost httpPost = new HttpPost(RANGER_URL + "/policy");
+ httpPost.setEntity(new StringEntity(Utils.getPayload(jsonFile)));
+ Utils.processHttpRequest(httpPost);
+ waitForPolicyRefresh();
+ }
+
+ protected void deletePolicy()
+ throws IOException {
+
+ log.info("Deleting policy " + policyName);
+ String requestUrl = RANGER_URL + "/policy?servicename=hawq&policyname=" + policyName;
+ Utils.processHttpRequest(new HttpDelete(requestUrl));
+ waitForPolicyRefresh();
+ }
+
+ protected boolean hasAccess(String user,
+ Map<String, String> resources,
+ List<String> privileges)
+ throws IOException {
+
+ log.info("Checking access for user " + user);
+ RPSRequest request = new RPSRequest(user, resources, privileges);
+ HttpPost httpPost = new HttpPost(RANGER_PLUGIN_SERVICE_URL);
+ httpPost.setEntity(new StringEntity(request.getJsonString()));
+ String result = Utils.processHttpRequest(httpPost);
+ RPSResponse rpsResponse = Utils.getResponse(result);
+ return rpsResponse.hasAccess();
+ }
+
+ private void waitForPolicyRefresh() {
+
+ try {
+ Thread.sleep(POLICY_REFRESH_INTERVAL);
+ }
+ catch (InterruptedException e) {
+ log.error(e);
+ }
+ }
+
+ public abstract void beforeTest() throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java
new file mode 100644
index 0000000..cfc41cb
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class TablespaceTest extends ServiceBaseTest {
+
+ private static final List<String> PRIVILEGES = Arrays.asList("create");
+
+ public void beforeTest()
+ throws IOException {
+ createPolicy("test-tablespace.json");
+ resources.put("tablespace", "pg_global");
+ }
+
+ @Test
+ public void testTablespaces_UserMaria_PgGlobalTablespace_Allowed()
+ throws IOException {
+ assertTrue(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testTablespaces_UserMaria_DoesNotExistTablespace_Denied()
+ throws IOException {
+ resources.put("tablespace", "doesnotexist");
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testTablespaces_UserBob_PgGlobalTablespace_Denied()
+ throws IOException {
+ assertFalse(hasAccess("bob", resources, PRIVILEGES));
+ }
+
+ @Test
+ public void testTablespaces_UserMaria_PgGlobalTablespace_Denied()
+ throws IOException {
+ deletePolicy();
+ assertFalse(hasAccess(RANGER_TEST_USER, resources, PRIVILEGES));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/Utils.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/Utils.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/Utils.java
new file mode 100644
index 0000000..971e513
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/Utils.java
@@ -0,0 +1,76 @@
+/*
+ * 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.hawq.ranger.integration.service.tests;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+
+public class Utils {
+
+ protected static final Log log = LogFactory.getLog(Utils.class);
+
+ public static String getPayload(String jsonFile)
+ throws IOException {
+ return IOUtils.toString(Utils.class.getClassLoader().getResourceAsStream(jsonFile));
+ }
+
+ public static String getEncoding() {
+ return Base64.encodeBase64String("admin:admin".getBytes());
+ }
+
+ public static String processHttpRequest(HttpRequestBase request)
+ throws IOException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Request URI = " + request.getURI().toString());
+ }
+ request.setHeader("Authorization", "Basic " + getEncoding());
+ request.setHeader("Content-Type", "application/json");
+ HttpClient httpClient = HttpClientBuilder.create().build();
+ HttpResponse response = httpClient.execute(request);
+ int responseCode = response.getStatusLine().getStatusCode();
+ log.info("Response Code = " + responseCode);
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ String result = IOUtils.toString(entity.getContent());
+ if (log.isDebugEnabled()) {
+ log.debug(result);
+ }
+ return result;
+ }
+ return null;
+ }
+
+ public static RPSResponse getResponse(String result)
+ throws IOException {
+ return new ObjectMapper().readValue(result, RPSResponse.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/log4j.properties b/ranger-plugin/integration/service/src/test/resources/log4j.properties
new file mode 100644
index 0000000..8578fd2
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/log4j.properties
@@ -0,0 +1,35 @@
+# 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.
+
+##-- To prevent junits from cluttering the build run by default all test runs send output to null appender
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+#hawq.ranger.root.logger=FATAL,devnull
+
+##-- uncomment the following line during during development/debugging so see debug messages during test run to be emitted to console
+hawq.ranger.root.logger=DEBUG,console
+log4j.rootLogger=${hawq.ranger.root.logger}
+log4j.logger.org.apache.http=WARN
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-database.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-database.json b/ranger-plugin/integration/service/src/test/resources/test-database.json
new file mode 100644
index 0000000..ffa3bfe
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-database.json
@@ -0,0 +1,46 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "DatabaseTest",
+ "policyType": 0,
+ "description": "Test policy for database resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "schema": {
+ "values": ["*"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "database": {
+ "values": ["sirotan"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "function": {
+ "values": ["*"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "create",
+ "isAllowed": true
+ }, {
+ "type": "connect",
+ "isAllowed": true
+ }, {
+ "type": "temp",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-function-2.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-function-2.json b/ranger-plugin/integration/service/src/test/resources/test-function-2.json
new file mode 100644
index 0000000..5ae7f0b
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-function-2.json
@@ -0,0 +1,40 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "FunctionTest",
+ "policyType": 0,
+ "description": "Test policy for function resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "schema": {
+ "values": ["*"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "database": {
+ "values": ["*"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "function": {
+ "values": ["atan"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "execute",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-function.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-function.json b/ranger-plugin/integration/service/src/test/resources/test-function.json
new file mode 100644
index 0000000..74d5d83
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-function.json
@@ -0,0 +1,40 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "FunctionTest",
+ "policyType": 0,
+ "description": "Test policy for function resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "schema": {
+ "values": ["siroschema"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "database": {
+ "values": ["sirotan"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "function": {
+ "values": ["atan"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "execute",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-language-2.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-language-2.json b/ranger-plugin/integration/service/src/test/resources/test-language-2.json
new file mode 100644
index 0000000..93a41fe
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-language-2.json
@@ -0,0 +1,35 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "LanguageTest",
+ "policyType": 0,
+ "description": "Test policy for language resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "language": {
+ "values": ["sql"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "database": {
+ "values": ["*"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "usage",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-language.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-language.json b/ranger-plugin/integration/service/src/test/resources/test-language.json
new file mode 100644
index 0000000..cba2f43
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-language.json
@@ -0,0 +1,35 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "LanguageTest",
+ "policyType": 0,
+ "description": "Test policy for language resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "language": {
+ "values": ["sql"],
+ "isExcludes": false,
+ "isRecursive": false
+ },
+ "database": {
+ "values": ["sirotan"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "usage",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-protocol.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-protocol.json b/ranger-plugin/integration/service/src/test/resources/test-protocol.json
new file mode 100644
index 0000000..d59caed
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-protocol.json
@@ -0,0 +1,33 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "ProtocolTest",
+ "policyType": 0,
+ "description": "Test policy for protocol resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "protocol": {
+ "values": ["pxf"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "select",
+ "isAllowed": true
+ }, {
+ "type": "insert",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/service/src/test/resources/test-tablespace.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/service/src/test/resources/test-tablespace.json b/ranger-plugin/integration/service/src/test/resources/test-tablespace.json
new file mode 100644
index 0000000..a45ecea
--- /dev/null
+++ b/ranger-plugin/integration/service/src/test/resources/test-tablespace.json
@@ -0,0 +1,30 @@
+{
+ "isEnabled": true,
+ "service": "hawq",
+ "name": "TablespaceTest",
+ "policyType": 0,
+ "description": "Test policy for tablespace resource",
+ "isAuditEnabled": true,
+ "resources": {
+ "tablespace": {
+ "values": ["pg_global"],
+ "isExcludes": false,
+ "isRecursive": false
+ }
+ },
+ "policyItems": [{
+ "accesses": [{
+ "type": "create",
+ "isAllowed": true
+ }],
+ "users": ["maria_dev"],
+ "groups": [],
+ "conditions": [],
+ "delegateAdmin": true
+ }],
+ "denyPolicyItems": [],
+ "allowExceptions": [],
+ "denyExceptions": [],
+ "dataMaskPolicyItems": [],
+ "rowFilterPolicyItems": []
+}
\ No newline at end of file
[4/4] incubator-hawq git commit: HAWQ-1203. Ranger Plugin Service
Implementation. (with contributions by Lav Jain and Leslie Chang) (close
#1092)
Posted by ad...@apache.org.
HAWQ-1203. Ranger Plugin Service Implementation. (with contributions by Lav Jain and Leslie Chang)
(close #1092)
Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/7f36b35b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/7f36b35b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/7f36b35b
Branch: refs/heads/master
Commit: 7f36b35bd059412b45444f613fb5b5e108a3a83e
Parents: e46f06c
Author: Alexander Denissov <ad...@pivotal.io>
Authored: Mon Jan 16 11:46:36 2017 -0800
Committer: Alexander Denissov <ad...@pivotal.io>
Committed: Wed Jan 18 10:57:09 2017 -0800
----------------------------------------------------------------------
.gitignore | 7 +
ranger-plugin/admin-plugin/pom.xml | 90 +++++
.../apache/hawq/ranger/model/HawqProtocols.java | 49 +++
.../apache/hawq/ranger/model/HawqResource.java | 29 ++
.../apache/hawq/ranger/service/HawqClient.java | 314 ++++++++++++++++++
.../hawq/ranger/service/HawqResourceMgr.java | 71 ++++
.../hawq/ranger/service/RangerServiceHawq.java | 66 ++++
.../hawq/ranger/service/HawqClientTest.java | 217 +++++++++++++
.../ranger/service/RangerServiceHawqTest.java | 90 +++++
.../src/test/resources/log4j.properties | 34 ++
ranger-plugin/conf/ranger-servicedef-hawq.json | 287 ++++++++++++++++
ranger-plugin/conf/tomcat-server.xml | 60 ++++
ranger-plugin/integration/admin/pom.xml | 70 ++++
.../integration/admin/ListDatabasesTest.java | 55 ++++
.../integration/admin/ListFunctionsTest.java | 250 ++++++++++++++
.../integration/admin/ListLanguagesTest.java | 118 +++++++
.../integration/admin/ListProtocolsTest.java | 55 ++++
.../integration/admin/ListSchemasTest.java | 126 +++++++
.../integration/admin/ListSequencesTest.java | 250 ++++++++++++++
.../integration/admin/ListTablesTest.java | 250 ++++++++++++++
.../integration/admin/ListTablespacesTest.java | 55 ++++
.../integration/admin/LookupTestBase.java | 65 ++++
.../src/test/resources/admin-tests-ddl.sql | 61 ++++
.../admin/src/test/resources/log4j.properties | 34 ++
ranger-plugin/integration/pom.xml | 67 ++++
ranger-plugin/integration/service/pom.xml | 68 ++++
.../integration/service/tests/DatabaseTest.java | 67 ++++
.../integration/service/tests/FunctionTest.java | 91 ++++++
.../integration/service/tests/LanguageTest.java | 83 +++++
.../integration/service/tests/ProtocolTest.java | 67 ++++
.../integration/service/tests/RPSRequest.java | 60 ++++
.../integration/service/tests/RPSResponse.java | 42 +++
.../service/tests/ServiceBaseTest.java | 116 +++++++
.../service/tests/TablespaceTest.java | 67 ++++
.../ranger/integration/service/tests/Utils.java | 76 +++++
.../service/src/test/resources/log4j.properties | 35 ++
.../src/test/resources/test-database.json | 46 +++
.../src/test/resources/test-function-2.json | 40 +++
.../src/test/resources/test-function.json | 40 +++
.../src/test/resources/test-language-2.json | 35 ++
.../src/test/resources/test-language.json | 35 ++
.../src/test/resources/test-protocol.json | 33 ++
.../src/test/resources/test-tablespace.json | 30 ++
ranger-plugin/pom.xml | 248 ++++++++++++++
ranger-plugin/scripts/register_hawq.sh | 217 +++++++++++++
ranger-plugin/scripts/rps.sh | 60 ++++
ranger-plugin/scripts/rps_env.sh | 30 ++
ranger-plugin/service/pom.xml | 88 +++++
.../ranger/authorization/HawqAuthorizer.java | 36 ++
.../authorization/RangerHawqAuthorizer.java | 263 +++++++++++++++
.../authorization/RangerHawqPluginResource.java | 86 +++++
.../authorization/ServiceExceptionMapper.java | 97 ++++++
.../apache/hawq/ranger/authorization/Utils.java | 80 +++++
.../model/AuthorizationRequest.java | 115 +++++++
.../model/AuthorizationResponse.java | 63 ++++
.../authorization/model/HawqPrivilege.java | 61 ++++
.../authorization/model/HawqResource.java | 46 +++
.../authorization/model/ResourceAccess.java | 85 +++++
.../service/src/main/resources/log4j.properties | 42 +++
.../src/main/resources/ranger-hawq-security.xml | 92 ++++++
.../service/src/main/resources/rps.properties | 17 +
.../service/src/main/webapp/WEB-INF/web.xml | 72 ++++
.../RangerHawqAuthorizerAppIdTest.java | 39 +++
.../authorization/RangerHawqAuthorizerTest.java | 325 +++++++++++++++++++
.../RangerHawqPluginResourceTest.java | 79 +++++
.../ServiceExceptionMapperTest.java | 61 ++++
.../hawq/ranger/authorization/UtilsTest.java | 48 +++
.../authorization/model/HawqPrivilegeTest.java | 71 ++++
.../authorization/model/HawqResourceTest.java | 48 +++
.../service/src/test/resources/log4j.properties | 42 +++
.../service/src/test/resources/rps.properties | 17 +
71 files changed, 6329 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 2076819..24039c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,12 @@ objfiles.txt
.pydevproject
.cproject
.settings
+.classpath
+
+# IDEA Project
+*.iml
+.idea
+
# Ctags
**/tags
@@ -54,6 +60,7 @@ env.sh
ext/
plr.tgz
autom4te.cache/
+**/target
# coverage
*.gcda
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/pom.xml b/ranger-plugin/admin-plugin/pom.xml
new file mode 100644
index 0000000..67c0824
--- /dev/null
+++ b/ranger-plugin/admin-plugin/pom.xml
@@ -0,0 +1,90 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-admin</artifactId>
+ <packaging>jar</packaging>
+ <name>HAWQ Ranger Admin Plugin</name>
+ <description>HAWQ Ranger Admin Plugin</description>
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+
+ <!-- Compilation Dependencies -->
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqProtocols.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqProtocols.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqProtocols.java
new file mode 100644
index 0000000..c6e51b0
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqProtocols.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hawq.ranger.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public enum HawqProtocols {
+
+ PROTOCOL_FILE("file"),
+ PROTOCOL_FTP("ftp"),
+ PROTOCOL_HTTP("http"),
+ PROTOCOL_GPFDIST("gpfdist"),
+ PROTOCOL_GPFDISTS("gpfdists"),
+ PROTOCOL_PXF("pxf");
+
+ private final String name;
+
+ private HawqProtocols(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static List<String> getAllProtocols() {
+ List<String> protocols = new ArrayList<>();
+ for(HawqProtocols protocol : HawqProtocols.values()) {
+ protocols.add(protocol.getName());
+ }
+ return protocols;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqResource.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqResource.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqResource.java
new file mode 100644
index 0000000..aae0b04
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/model/HawqResource.java
@@ -0,0 +1,29 @@
+/*
+ * 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.hawq.ranger.model;
+
+public enum HawqResource {
+ DATABASE,
+ SCHEMA,
+ TABLE,
+ SEQUENCE,
+ FUNCTION,
+ LANGUAGE,
+ TABLESPACE,
+ PROTOCOL
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java
new file mode 100644
index 0000000..d2606be
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java
@@ -0,0 +1,314 @@
+/*
+ * 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.hawq.ranger.service;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.model.HawqProtocols;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.util.*;
+
+import static org.apache.ranger.plugin.client.BaseClient.generateResponseDataMap;
+
+public class HawqClient {
+
+ private static final Log LOG = LogFactory.getLog(HawqClient.class);
+
+ public static final String CONNECTION_SUCCESSFUL_MESSAGE = "ConnectionTest Successful";
+ public static final String CONNECTION_FAILURE_MESSAGE = "Unable to retrieve any databases using given parameters.";
+
+ public static final String DATABASE_LIST_QUERY = "SELECT datname from pg_database WHERE " +
+ "datname NOT IN ('template0', 'template1', 'hcatalog') and datname LIKE ?";
+ public static final String TABLESPACE_LIST_QUERY = "SELECT spcname from pg_tablespace WHERE spcname LIKE ?";
+ public static final String PROTOCOL_LIST_QUERY = "SELECT ptcname from pg_catalog.pg_extprotocol WHERE ptcname LIKE ?";
+ public static final String SCHEMA_LIST_QUERY = "SELECT schema_name from information_schema.schemata WHERE " +
+ "schema_name NOT IN ('pg_catalog', 'information_schema', 'hawq_toolkit', 'pg_bitmapindex', 'pg_aoseg') AND schema_name NOT LIKE 'pg_toast%' AND schema_name LIKE ?";
+ public static final String LANGUAGE_LIST_QUERY = "SELECT lanname from pg_language WHERE lanname LIKE ?";
+ public static final String SEQUENCE_LIST_QUERY = "SELECT schemaname, relname from pg_statio_all_sequences WHERE relname LIKE ?";
+ public static final String FUNCTION_LIST_QUERY = "SELECT n.nspname, p.proname FROM pg_catalog.pg_proc p " +
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname NOT IN " +
+ "('pg_catalog', 'information_schema', 'hawq_toolkit', 'pg_bitmapindex', 'pg_aoseg') AND n.nspname NOT LIKE 'pg_toast%' AND p.proname LIKE ?";
+ public static final String TABLE_LIST_QUERY = "SELECT c.relname, n.nspname FROM pg_catalog.pg_class c " +
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','','v') AND n.nspname NOT IN " +
+ "('pg_catalog', 'information_schema', 'hawq_toolkit', 'pg_bitmapindex', 'pg_aoseg') AND n.nspname NOT LIKE 'pg_toast%' AND c.relname LIKE ?";
+
+ public static final String DATNAME = "datname";
+ public static final String SPCNAME = "spcname";
+ public static final String PTCNAME = "ptcname";
+ public static final String SCHEMA_NAME = "schema_name";
+ public static final String LANGUAGE_NAME = "lanname";
+ public static final String RELNAME = "relname";
+ public static final String SCHEMANAME = "schemaname";
+ public static final String PRONAME = "proname";
+ public static final String NSPNAME = "nspname";
+ public static final String WILDCARD = "*";
+
+ public static final List<String> INTERNAL_PROTOCOLS = HawqProtocols.getAllProtocols();
+ private static final String DEFAULT_DATABASE = "postgres";
+ private static final String JDBC_DRIVER_CLASS = "org.postgresql.Driver";
+
+ private Map<String, String> connectionProperties;
+
+ // we need to load class for the Postgres Driver directly to allow it to register with DriverManager
+ // since DriverManager's classloader will not be able to find it by itself due to plugin's special classloaders
+ static {
+ try {
+ Class.forName(JDBC_DRIVER_CLASS);
+ } catch (Throwable e) {
+ LOG.error("<== HawqClient.initializer : Unable to load JDBC driver " + JDBC_DRIVER_CLASS + " : " + e.getMessage());
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ public HawqClient(Map<String, String> connectionProperties) throws SQLException {
+ this.connectionProperties = connectionProperties;
+ }
+
+ /**
+ * Uses the connectionProperties and attempts to connect to Hawq.
+ * Returns a message depending on success or failure.
+ *
+ * @param connectionProperties Map which contains hostname, port, username, and password
+ * @return Map which contains connectivityStatus, message, description, objectId, and fieldName
+ */
+
+ public HashMap<String, Object> checkConnection(Map<String, String> connectionProperties) throws Exception {
+
+ boolean isConnected = false;
+ HashMap<String, Object> result = new HashMap<>();
+ Connection conn = null;
+
+ String description = CONNECTION_FAILURE_MESSAGE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.checkConnection Starting connection to hawq");
+ }
+
+ try {
+ conn = getConnection(connectionProperties);
+ if(conn.getCatalog() != null) {
+ isConnected = true;
+ description = CONNECTION_SUCCESSFUL_MESSAGE;
+ }
+ } catch (SQLException e) {
+ LOG.error("<== HawqClient.checkConnection Error: Failed to connect" + e);
+ description = e.getMessage();
+ } finally {
+ closeConnection(conn);
+ }
+
+ String message = isConnected ? CONNECTION_SUCCESSFUL_MESSAGE : CONNECTION_FAILURE_MESSAGE;
+
+ generateResponseDataMap(isConnected, message, description, null, null, result);
+
+ return result;
+ }
+
+ public List<String> getDatabaseList(String userInput) throws SQLException {
+ return queryHawq(userInput, DATNAME, DATABASE_LIST_QUERY, null);
+ }
+
+ public List<String> getTablespaceList(String userInput) throws SQLException {
+ return queryHawq(userInput, SPCNAME, TABLESPACE_LIST_QUERY, null);
+ }
+
+ public List<String> getProtocolList(String userInput) throws SQLException {
+ Set<String> allProtocols = new HashSet<>();
+ for (String protocol : INTERNAL_PROTOCOLS) {
+ if(protocol.startsWith(userInput) || userInput.equals(WILDCARD)) {
+ allProtocols.add(protocol);
+ }
+ }
+ allProtocols.addAll(queryHawq(userInput, PTCNAME, PROTOCOL_LIST_QUERY, null));
+ return new ArrayList<>(allProtocols);
+ }
+
+ public List<String> getSchemaList(String userInput, Map<String, List<String>> resources) throws SQLException {
+ return queryHawqPerDb(userInput, resources.get("database"), SCHEMA_NAME, SCHEMA_LIST_QUERY);
+ }
+
+ public List<String> getLanguageList(String userInput, Map<String, List<String>> resources) throws SQLException {
+ return queryHawqPerDb(userInput, resources.get("database"), LANGUAGE_NAME, LANGUAGE_LIST_QUERY);
+ }
+
+ public List<String> getTableList(String userInput, Map<String, List<String>> resources) throws SQLException {
+ return queryHawqPerDbAndSchema(userInput, resources, NSPNAME, RELNAME, TABLE_LIST_QUERY);
+ }
+
+ public List<String> getSequenceList(String userInput, Map<String, List<String>> resources) throws SQLException {
+ return queryHawqPerDbAndSchema(userInput, resources, SCHEMANAME, RELNAME, SEQUENCE_LIST_QUERY);
+ }
+
+ public List<String> getFunctionList(String userInput, Map<String, List<String>> resources) throws SQLException {
+ return queryHawqPerDbAndSchema(userInput, resources, NSPNAME, PRONAME, FUNCTION_LIST_QUERY);
+ }
+
+ private List<String> queryHawqPerDb(String userInput, List<String> databases, String columnName, String query) throws SQLException {
+ Set<String> uniqueResults = new HashSet<>();
+
+ //do for all databases
+ if (databases.contains(WILDCARD)) {
+ databases = getDatabaseList(WILDCARD);
+ }
+
+ for (String db : databases) {
+ uniqueResults.addAll(queryHawq(userInput, columnName, query, db));
+ }
+ return new ArrayList<>(uniqueResults);
+ }
+
+ private List<String> queryHawqPerDbAndSchema(String userInput, Map<String, List<String>> resources, String schemaColumnName, String resultColumnName, String query) throws SQLException {
+ Set<String> uniqueResults = new HashSet<>();
+ List<String> databases = resources.get("database");
+ List<String> schemas = resources.get("schema");
+
+ Connection conn = null;
+ PreparedStatement preparedStatement = null;
+ ResultSet resultSet = null;
+
+ if (databases.contains(WILDCARD)) {
+ databases = getDatabaseList(WILDCARD);
+ }
+
+ for (String db: databases) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.queryHawqPerDbAndSchema: Connecting to db: " + db);
+ }
+
+ try {
+ conn = getConnection(connectionProperties, db);
+ preparedStatement = handleWildcardPreparedStatement(userInput, query, conn);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.queryHawqPerDbAndSchema Starting query: " + query);
+ }
+
+ resultSet = preparedStatement.executeQuery();
+
+ while(resultSet.next()) {
+ if(schemas.contains(resultSet.getString(schemaColumnName)) || schemas.contains(WILDCARD)) {
+ uniqueResults.add(resultSet.getString(resultColumnName));
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.queryHawqPerDbAndSchema Query result: " + uniqueResults.toString());
+ }
+
+ } catch (SQLException e) {
+ LOG.error("<== HawqClient.queryHawqPerDbAndSchema Error: Failed to get results for query: " + query + ", Error: " + e);
+ } finally {
+ closeResultSet(resultSet);
+ closeStatement(preparedStatement);
+ closeConnection(conn);
+ }
+ }
+ return new ArrayList<>(uniqueResults);
+ }
+
+ private List<String> queryHawq(String userInput, String columnName, String query, String database) {
+ List<String> result = new ArrayList<>();
+ Connection conn = null;
+ PreparedStatement preparedStatement = null;
+ ResultSet resultSet = null;
+
+ try {
+ conn = getConnection(connectionProperties, database);
+ preparedStatement = handleWildcardPreparedStatement(userInput, query, conn);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.queryHawq Starting query: " + query);
+ }
+
+ resultSet = preparedStatement.executeQuery();
+
+ while(resultSet.next()) {
+ result.add(resultSet.getString(columnName));
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.queryHawq Query result: " + result.toString());
+ }
+
+ } catch (SQLException e) {
+ LOG.error("<== HawqClient.queryHawq Error: Failed to get result from query: " + query + ", Error: " + e);
+ } finally {
+ closeResultSet(resultSet);
+ closeStatement(preparedStatement);
+ closeConnection(conn);
+ }
+
+ return result;
+ }
+
+ private Connection getConnection(Map<String, String> connectionProperties) throws SQLException {
+ return getConnection(connectionProperties, null);
+ }
+
+ private Connection getConnection(Map<String, String> connectionProperties, String database) throws SQLException {
+
+ String db = database != null ? database : DEFAULT_DATABASE;
+ String url = String.format("jdbc:postgresql://%s:%s/%s", connectionProperties.get("hostname"), connectionProperties.get("port"), db);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== HawqClient.checkConnection Connecting to: (" + url + ") with user: " + connectionProperties.get("username") );
+ }
+
+ Properties props = new Properties();
+ props.setProperty("user", connectionProperties.get("username"));
+ props.setProperty("password", connectionProperties.get("password"));
+ return DriverManager.getConnection(url, props);
+ }
+
+ private PreparedStatement handleWildcardPreparedStatement(String userInput, String query, Connection conn) throws SQLException {
+ PreparedStatement preparedStatement = conn.prepareStatement(query);
+ preparedStatement.setString(1, userInput.equals(WILDCARD) ? "%" : (userInput + "%"));
+ return preparedStatement;
+ }
+
+ private void closeResultSet(ResultSet rs) {
+ try {
+ if (rs != null) rs.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ private void closeStatement(PreparedStatement st) {
+ try {
+ if (st != null) st.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ private void closeConnection(Connection conn) {
+ try {
+ if (conn != null) conn.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java
new file mode 100644
index 0000000..214ebdb
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hawq.ranger.service;
+
+import org.apache.hawq.ranger.model.HawqResource;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+public abstract class HawqResourceMgr {
+
+ public static List<String> getHawqResources(Map<String, String> configs,
+ ResourceLookupContext context) throws SQLException {
+ String userInput = context.getUserInput();
+ HawqResource hawqResource = HawqResource.valueOf(context.getResourceName().toUpperCase());
+ Map<String, List<String>> resources = context.getResources();
+
+ List<String> result;
+ HawqClient hawqClient = new HawqClient(configs);
+
+ switch (hawqResource) {
+ case DATABASE:
+ result = hawqClient.getDatabaseList(userInput);
+ break;
+ case TABLESPACE:
+ result = hawqClient.getTablespaceList(userInput);
+ break;
+ case PROTOCOL:
+ result = hawqClient.getProtocolList(userInput);
+ break;
+ case SCHEMA:
+ result = hawqClient.getSchemaList(userInput, resources);
+ break;
+ case LANGUAGE:
+ result = hawqClient.getLanguageList(userInput, resources);
+ break;
+ case TABLE:
+ result = hawqClient.getTableList(userInput, resources);
+ break;
+ case SEQUENCE:
+ result = hawqClient.getSequenceList(userInput, resources);
+ break;
+ case FUNCTION:
+ result = hawqClient.getFunctionList(userInput, resources);
+ break;
+ default:
+ throw new IllegalArgumentException("Resource requested does not exist.");
+ }
+
+ Collections.sort(result);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java
new file mode 100644
index 0000000..0f12191
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java
@@ -0,0 +1,66 @@
+/*
+ * 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.hawq.ranger.service;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.service.RangerBaseService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+
+import java.util.*;
+
+public class RangerServiceHawq extends RangerBaseService {
+
+ private static final Log LOG = LogFactory.getLog(RangerServiceHawq.class);
+
+ @Override
+ public HashMap<String, Object> validateConfig() throws Exception {
+ boolean isDebugEnabled = LOG.isDebugEnabled();
+
+ if(isDebugEnabled) {
+ LOG.debug("==> RangerServiceHawq.validateConfig Service: (hawq)");
+ }
+
+ HashMap<String, Object> result = new HashMap<>();
+
+ if (configs != null) {
+ try {
+ HawqClient hawqClient = new HawqClient(configs);
+ result = hawqClient.checkConnection(configs);
+ } catch (HadoopException e) {
+ LOG.error("<== RangerServiceHawq.validateConfig Error:" + e);
+ throw e;
+ }
+ }
+
+ if (isDebugEnabled) {
+ LOG.debug("<== RangerServiceHawq.validateConfig Response : (" + result + ")");
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> lookupResource(ResourceLookupContext context) throws Exception {
+ List<String> resources = HawqResourceMgr.getHawqResources(getConfigs(), context);
+
+ return resources;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java
new file mode 100644
index 0000000..7d624d8
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.hawq.ranger.service;
+
+import org.apache.ranger.plugin.client.BaseClient;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.apache.hawq.ranger.service.HawqClient.*;
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
+import static org.mockito.Matchers.anyString;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(HawqClient.class)
+public class HawqClientTest {
+
+ @Mock
+ public Connection conn;
+ @Mock
+ public PreparedStatement preparedStatement;
+ @Mock
+ public ResultSet resultSet;
+
+ public HawqClient hawqClientSpy;
+
+ public HawqClient hawqClient;
+ private Map<String, String> connectionProperties;
+ private Map<String, List<String>> resources;
+
+ @Before
+ public void setUp() throws SQLException {
+ connectionProperties = new HashMap<>();
+ connectionProperties.put("hostname", "hostname");
+ connectionProperties.put("port", "5432");
+ connectionProperties.put("hostname", "hostname");
+ connectionProperties.put("username", "username");
+ connectionProperties.put("password", "password");
+
+ mockStatic(DriverManager.class);
+ suppress(constructor(BaseClient.class, String.class, Map.class));
+ hawqClient = new HawqClient(connectionProperties);
+
+ hawqClientSpy = PowerMockito.spy(hawqClient);
+
+ resources = new HashMap<>();
+ List<String> dbs = Arrays.asList("db1", "db2");
+ List<String> schemas = Arrays.asList("schema1", "schema2");
+ resources.put("database", dbs);
+ resources.put("schema", schemas);
+ }
+
+ @Test
+ public void testCheckConnection_Failure() throws Exception {
+ when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn);
+ when(conn.getCatalog()).thenReturn(null);
+ Map<String, Object> response = hawqClient.checkConnection(connectionProperties);
+ assertEquals(CONNECTION_FAILURE_MESSAGE, response.get("message"));
+ assertFalse((Boolean) response.get("connectivityStatus"));
+ }
+
+ @Test
+ public void testCheckConnection_Success() throws Exception {
+ when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn);
+ when(conn.getCatalog()).thenReturn("catalog");
+ Map<String, Object> response = hawqClient.checkConnection(connectionProperties);
+ assertEquals(CONNECTION_SUCCESSFUL_MESSAGE, response.get("message"));
+ assertTrue((Boolean) response.get("connectivityStatus"));
+ }
+
+ @Test
+ public void testCheckConnection_ThrowsSQLException_Failure() throws Exception {
+ when(DriverManager.getConnection(anyString(), any(Properties.class))).thenThrow(new SQLException("Failed to connect"));
+ Map<String, Object> response = hawqClient.checkConnection(connectionProperties);
+ assertEquals(CONNECTION_FAILURE_MESSAGE, response.get("message"));
+ assertEquals("Failed to connect", response.get("description"));
+ assertFalse((Boolean) response.get("connectivityStatus"));
+ }
+
+ @Test
+ public void testDatabaseList_Success() throws Exception {
+ when(conn.prepareStatement(DATABASE_LIST_QUERY)).thenReturn(preparedStatement);
+ when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
+ when(resultSet.getString(DATNAME)).thenReturn("db1").thenReturn("db2");
+ PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString());
+ assertEquals(Arrays.asList("db1", "db2"), hawqClientSpy.getDatabaseList("d"));
+ }
+
+ @Test
+ public void testTablespaceList_Success() throws Exception {
+ doReturn(Arrays.asList("tablespace1", "tablespace2")).when(hawqClientSpy, "queryHawq", "t", SPCNAME, TABLESPACE_LIST_QUERY, null);
+ assertEquals(Arrays.asList("tablespace1", "tablespace2"), hawqClientSpy.getTablespaceList("t"));
+ }
+
+ @Test
+ public void testProtocolList_Success() throws Exception {
+ List<String> expectedResult = Arrays.asList("protocol1", "protocol2", "pxf");
+ doReturn(Arrays.asList("protocol1", "protocol2")).when(hawqClientSpy, "queryHawq", "p", PTCNAME, PROTOCOL_LIST_QUERY, null);
+ List<String> result = hawqClientSpy.getProtocolList("p");
+ Collections.sort(result);
+ assertEquals(expectedResult, result);
+ }
+
+ @Test
+ public void testSchemaList_MultipleDb_Success() throws Exception {
+ doReturn(Arrays.asList("schema1")).when(hawqClientSpy, "queryHawq", "s", SCHEMA_NAME, SCHEMA_LIST_QUERY, "db1");
+ doReturn(Arrays.asList("schema2")).when(hawqClientSpy, "queryHawq", "s", SCHEMA_NAME, SCHEMA_LIST_QUERY, "db2");
+ List<String> result = hawqClientSpy.getSchemaList("s", resources);
+ Collections.sort(result);
+ assertEquals(Arrays.asList("schema1", "schema2"), result);
+ }
+
+ @Test
+ public void testSchemaList_AllDb_Success() throws Exception {
+ resources.put("database", Arrays.asList(WILDCARD));
+ doReturn(Arrays.asList("db1", "db2", "db3")).when(hawqClientSpy, "getDatabaseList", WILDCARD);
+ doReturn(Arrays.asList("schema1")).when(hawqClientSpy, "queryHawq", "s", SCHEMA_NAME, SCHEMA_LIST_QUERY, "db1");
+ doReturn(Arrays.asList("schema2")).when(hawqClientSpy, "queryHawq", "s", SCHEMA_NAME, SCHEMA_LIST_QUERY, "db2");
+ doReturn(Arrays.asList("schema3")).when(hawqClientSpy, "queryHawq", "s", SCHEMA_NAME, SCHEMA_LIST_QUERY, "db3");
+ List<String> result = hawqClientSpy.getSchemaList("s", resources);
+ Collections.sort(result);
+ assertEquals(Arrays.asList("schema1", "schema2", "schema3"), result);
+ }
+
+ @Test
+ public void testLanguageList_Success() throws Exception {
+ doReturn(Arrays.asList("language1")).when(hawqClientSpy, "queryHawq", "l", LANGUAGE_NAME, LANGUAGE_LIST_QUERY, "db1");
+ doReturn(Arrays.asList("language2")).when(hawqClientSpy, "queryHawq", "l", LANGUAGE_NAME, LANGUAGE_LIST_QUERY, "db2");
+ List<String> result = hawqClientSpy.getLanguageList("l", resources);
+ Collections.sort(result);
+ assertEquals(Arrays.asList("language1", "language2"), result);
+ }
+
+ @Test
+ public void testTableList_Success() throws Exception {
+ PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString());
+ when(conn.prepareStatement(TABLE_LIST_QUERY)).thenReturn(preparedStatement);
+ when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
+ when(resultSet.getString(RELNAME)).thenReturn("table1").thenReturn("table2");
+ when(resultSet.getString(NSPNAME)).thenReturn("schema1").thenReturn("schema2");
+ List<String> result = hawqClientSpy.getTableList("t", resources);
+ Collections.sort(result);
+ assertEquals(Arrays.asList("table1", "table2"), result);
+ }
+
+ @Test
+ public void testSequenceList_Success() throws Exception {
+ PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString());
+ when(conn.prepareStatement(SEQUENCE_LIST_QUERY)).thenReturn(preparedStatement);
+ when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
+ when(resultSet.getString(RELNAME)).thenReturn("seq1").thenReturn("seq2");
+ when(resultSet.getString(SCHEMANAME)).thenReturn("schema1").thenReturn("schema2");
+ List<String> result = hawqClientSpy.getSequenceList("s", resources);
+ Collections.sort(result);
+ assertEquals(Arrays.asList("seq1", "seq2"), result);
+ }
+
+ @Test
+ public void testSequenceList_SchemaFiltered_Success() throws Exception {
+ PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString());
+ when(conn.prepareStatement(SEQUENCE_LIST_QUERY)).thenReturn(preparedStatement);
+ when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
+ when(resultSet.getString(RELNAME)).thenReturn("seq1").thenReturn("seq2");
+ when(resultSet.getString(SCHEMANAME)).thenReturn("schema1").thenReturn("schema3");
+ assertEquals(Arrays.asList("seq1"), hawqClientSpy.getSequenceList("s", resources));
+ }
+
+ @Test
+ public void testFunctionList_Success() throws Exception {
+ PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString());
+ when(conn.prepareStatement(FUNCTION_LIST_QUERY)).thenReturn(preparedStatement);
+ when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
+ when(resultSet.getString(PRONAME)).thenReturn("fxn1").thenReturn("fxn2");
+ when(resultSet.getString(NSPNAME)).thenReturn("schema1").thenReturn("schema2");
+ assertEquals(Arrays.asList("fxn1", "fxn2"), hawqClientSpy.getFunctionList("f", resources));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java
new file mode 100644
index 0000000..5264929
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.hawq.ranger.service;
+
+import org.apache.ranger.plugin.client.BaseClient;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.apache.hawq.ranger.service.HawqClient.CONNECTION_SUCCESSFUL_MESSAGE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(HawqClient.class)
+public class RangerServiceHawqTest {
+
+ private RangerServiceHawq service;
+ private Map<String, String> configs;
+
+ @Mock
+ HawqClient mockHawqClient;
+ @Mock
+ Connection conn;
+
+ @Before
+ public void setup() {
+ service = new RangerServiceHawq();
+ service.setServiceName("hawq");
+ service.setServiceType("hawq");
+
+ configs = new HashMap<>();
+ configs.put("username", "username");
+ configs.put("password", "password");
+ configs.put("hostname", "localhost");
+ configs.put("port", "5432");
+
+ service.setConfigs(configs);
+
+ mockStatic(DriverManager.class);
+ }
+
+ @Test
+ public void testValidateConfigSuccess() throws Exception {
+ HashMap<String, Object> result = new HashMap<>();
+ result.put("message", "ConnectionTest Successful");
+ result.put("description", "ConnectionTest Successful");
+ result.put("connectivityStatus", true);
+
+ suppress(constructor(BaseClient.class, String.class, Map.class));
+ PowerMockito.when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn);
+ when(conn.getCatalog()).thenReturn("catalog");
+
+ HashMap<String, Object> response = service.validateConfig();
+ assertEquals(CONNECTION_SUCCESSFUL_MESSAGE, response.get("description"));
+ assertEquals(CONNECTION_SUCCESSFUL_MESSAGE, response.get("message"));
+ assertTrue((Boolean) response.get("connectivityStatus"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/admin-plugin/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/admin-plugin/src/test/resources/log4j.properties b/ranger-plugin/admin-plugin/src/test/resources/log4j.properties
new file mode 100644
index 0000000..903f0b6
--- /dev/null
+++ b/ranger-plugin/admin-plugin/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+# 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.
+
+##-- To prevent junits from cluttering the build run by default all test runs send output to null appender
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+#hawq.ranger.root.logger=FATAL,devnull
+
+##-- uncomment the following line during during development/debugging so see debug messages during test run to be emitted to console
+hawq.ranger.root.logger=DEBUG,console
+log4j.rootLogger=${hawq.ranger.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/conf/ranger-servicedef-hawq.json
----------------------------------------------------------------------
diff --git a/ranger-plugin/conf/ranger-servicedef-hawq.json b/ranger-plugin/conf/ranger-servicedef-hawq.json
new file mode 100644
index 0000000..03005bc
--- /dev/null
+++ b/ranger-plugin/conf/ranger-servicedef-hawq.json
@@ -0,0 +1,287 @@
+{
+ "name": "hawq",
+ "implClass": "org.apache.hawq.ranger.service.RangerServiceHawq",
+ "label": "HAWQ",
+ "description": "HAWQ",
+ "guid": "1ebb27ee-549a-401d-85ab-818342ca54af",
+ "resources":
+ [
+ {
+ "itemId": 1,
+ "name": "database",
+ "type": "string",
+ "level": 10,
+ "parent": "",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Database",
+ "description": "HAWQ Database"
+ },
+ {
+ "itemId": 2,
+ "name": "schema",
+ "type": "string",
+ "level": 20,
+ "parent": "database",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Schema",
+ "description": "HAWQ Schema"
+ },
+ {
+ "itemId": 3,
+ "name": "table",
+ "type": "string",
+ "level": 30,
+ "parent": "schema",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Table",
+ "description": "HAWQ Table"
+ },
+ {
+ "itemId": 4,
+ "name": "sequence",
+ "type": "string",
+ "level": 30,
+ "parent": "schema",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Sequence",
+ "description": "HAWQ Sequence"
+ },
+ {
+ "itemId": 5,
+ "name": "function",
+ "type": "string",
+ "level": 30,
+ "parent": "schema",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Function",
+ "description": "HAWQ Function"
+ },
+ {
+ "itemId": 6,
+ "name": "language",
+ "type": "string",
+ "level": 20,
+ "parent": "database",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Language",
+ "description": "HAWQ Language"
+ },
+ {
+ "itemId": 7,
+ "name": "tablespace",
+ "type": "string",
+ "level": 10,
+ "parent": "",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Tablespace",
+ "description": "HAWQ Tablespace"
+ },
+ {
+ "itemId": 8,
+ "name": "protocol",
+ "type": "string",
+ "level": 10,
+ "parent": "",
+ "mandatory": true,
+ "lookupSupported": true,
+ "recursiveSupported": false,
+ "excludesSupported": true,
+ "Matcher": "org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+ "matcherOptions": {"wildCard":true, "ignoreCase":true},
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "Protocol",
+ "description": "HAWQ Protocol"
+ }
+ ],
+ "accessTypes":
+ [
+ {
+ "itemId": 1,
+ "name": "select",
+ "label": "select"
+ },
+ {
+ "itemId": 2,
+ "name": "insert",
+ "label": "insert"
+ },
+ {
+ "itemId": 3,
+ "name": "update",
+ "label": "update"
+ },
+ {
+ "itemId": 4,
+ "name": "delete",
+ "label": "delete"
+ },
+ {
+ "itemId": 5,
+ "name": "references",
+ "label": "references"
+ },
+ {
+ "itemId": 6,
+ "name": "usage",
+ "label": "usage"
+ },
+ {
+ "itemId": 7,
+ "name": "create",
+ "label": "create"
+ },
+ {
+ "itemId": 8,
+ "name": "connect",
+ "label": "connect"
+ },
+ {
+ "itemId": 9,
+ "name": "execute",
+ "label": "execute"
+ },
+ {
+ "itemId": 10,
+ "name": "temp",
+ "label": "temp"
+ },
+ {
+ "itemId": 11,
+ "name": "create-schema",
+ "label": "create-schema"
+ },
+ {
+ "itemId": 12,
+ "name": "usage-schema",
+ "label": "usage-schema"
+ },
+ {
+ "itemId": 13,
+ "name": "all",
+ "label": "All",
+ "impliedGrants": [
+ "select",
+ "insert",
+ "update",
+ "delete",
+ "references",
+ "usage",
+ "create",
+ "connect",
+ "execute",
+ "temp",
+ "create-schema",
+ "usage-schema"
+ ]
+ }
+ ],
+
+ "configs":
+ [
+ {
+ "itemId": 1,
+ "name": "username",
+ "type": "string",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "HAWQ User Name",
+ "defaultValue": "gpadmin"
+ },
+ {
+ "itemId": 2,
+ "name": "password",
+ "type": "password",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "HAWQ User Password"
+ },
+ {
+ "itemId": 3,
+ "name": "hostname",
+ "type": "string",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "HAWQ Master Hostname"
+ },
+ {
+ "itemId": 4,
+ "name": "port",
+ "type": "int",
+ "mandatory": true,
+ "validationRegEx": "",
+ "validationMessage": "",
+ "uiHint": "",
+ "label": "HAWQ Master Port",
+ "defaultValue": 5432
+ }
+ ],
+ "enums": [],
+ "contextEnrichers": [],
+ "policyConditions": [],
+ "dataMaskDef": {},
+ "rowFilterDef": {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/conf/tomcat-server.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/conf/tomcat-server.xml b/ranger-plugin/conf/tomcat-server.xml
new file mode 100644
index 0000000..09f9088
--- /dev/null
+++ b/ranger-plugin/conf/tomcat-server.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.
+-->
+<!-- Note: A "Server" is not itself a "Container", so you may not
+ define subcomponents such as "Valves" at this level.
+ Documentation at /docs/config/server.html
+ -->
+<Server port="8005" shutdown="SHUTDOWN">
+
+ <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
+ <Listener className="org.apache.catalina.core.JasperListener" />
+ <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
+ <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
+ <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+
+ <GlobalNamingResources>
+ <Resource name="UserDatabase" auth="Container"
+ type="org.apache.catalina.UserDatabase"
+ description="User database that can be updated and saved"
+ factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+ pathname="conf/tomcat-users.xml" />
+ </GlobalNamingResources>
+
+ <Service name="Catalina">
+
+ <Connector port="${http.port}" protocol="HTTP/1.1"
+ connectionTimeout="20000"
+ redirectPort="8443" />
+
+ <Engine name="Catalina" defaultHost="localhost">
+
+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+ resourceName="UserDatabase"/>
+
+ <Host name="${http.host}" appBase="webapps"
+ unpackWARs="true" autoDeploy="true"
+ xmlValidation="false" xmlNamespaceAware="false">
+
+ <Context path="/rps"
+ docBase="/usr/local/hawq/ranger/plugin-service/webapps/rps"
+ reloadable="false" debug="0" cookies="false"></Context>
+
+ </Host>
+ </Engine>
+ </Service>
+</Server>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/pom.xml b/ranger-plugin/integration/admin/pom.xml
new file mode 100644
index 0000000..0a81941
--- /dev/null
+++ b/ranger-plugin/integration/admin/pom.xml
@@ -0,0 +1,70 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-integration-admin</artifactId>
+ <packaging>jar</packaging>
+ <name>HAWQ Ranger Plugin - Integration Tests for Admin Plugin</name>
+ <description>HAWQ Ranger Plugin - Integration Tests for Admin Plugin</description>
+
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-integration</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-admin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListDatabasesTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListDatabasesTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListDatabasesTest.java
new file mode 100644
index 0000000..67eecdd
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListDatabasesTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListDatabasesTest extends LookupTestBase {
+
+ private static final Set<String> DATABASES = Sets.newHashSet("postgres", "east", "west", "noschema_db");
+
+ @Test
+ public void testListDatabases_All() throws Exception {
+ List<String> result = service.lookupResource(getContext("database", "*"));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet(DATABASES)));
+ }
+
+ @Test
+ public void testListDatabases_FilteredPresent() throws Exception {
+ List<String> result = service.lookupResource(getContext("database", "e"));
+ assertEquals(1, result.size());
+ assertEquals(result.get(0), "east");
+ }
+
+ @Test
+ public void testListDatabases_FilteredAbsent() throws Exception {
+ List<String> result = service.lookupResource(getContext("database", "z"));
+ assertTrue(result.isEmpty());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListFunctionsTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListFunctionsTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListFunctionsTest.java
new file mode 100644
index 0000000..7b68d78
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListFunctionsTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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 schema governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListFunctionsTest extends LookupTestBase {
+
+ private Map<String, List<String>> resources;
+
+ @Before
+ public void setUp() {
+ resources = new HashMap<>();
+ }
+
+ @Test
+ public void testListFunctions_NoSchemaDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("noschema_db"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_SingleSchema_AllFilter_NoFunctions() throws Exception {
+ resources.put("database", Arrays.asList("west"));
+ resources.put("schema", Arrays.asList("jamaica"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_TwoSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "sleep", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "sleep", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDb_CommonSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "sleep")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDb_SingleSchema_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "sleep", "stand", "smile")));
+ }
+
+ @Test
+ public void testListFunctions_AllDb_AllSchemas_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat", "sleep", "stand", "smile")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_TwoSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_CommonSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_SingleSchema_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_AllDbs_AllSchemas_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("stand")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_TwoSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("common", "japan"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sleep", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sleep", "stand")));
+ }
+
+ @Test
+ public void testListFunctions_SingleDb_AllSchemas_FilteredPresent2() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "e", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_CommonSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("common"));
+ List<String> result = service.lookupResource(getContext("function", "e", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("eat")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_SingleSchema_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("japan"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("stand")));
+ }
+
+ @Test
+ public void testListFunctions_TwoDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sleep", "stand", "smile")));
+ }
+
+ @Test
+ public void testListFunctions_AllDbs_AllSchemas_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ resources.put("schema", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("function", "s", resources));
+ assertEquals(3, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("sleep", "stand", "smile")));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListLanguagesTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListLanguagesTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListLanguagesTest.java
new file mode 100644
index 0000000..726ef7e
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListLanguagesTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListLanguagesTest extends LookupTestBase {
+
+ private static final Set<String> DEFAULT_LANGUAGES = Sets.newHashSet("c", "internal", "plpgsql", "sql");
+ private static final Set<String> EAST_LANGUAGES = Sets.newHashSet("langdbeast", "c", "internal", "plpgsql", "sql");
+
+ private Map<String, List<String>> resources = new HashMap<>();
+
+ @Test
+ public void testListLanguage_NoResources() throws Exception {
+ resources.put("database", Arrays.asList("noschema_db"));
+ List<String> result = service.lookupResource(getContext("language", "*", resources));
+ assertEquals(4, result.size());
+ assertTrue(Sets.newHashSet(result).equals(DEFAULT_LANGUAGES));
+ }
+
+ @Test
+ public void testListLanguages_SingleDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("language", "*", resources));
+ assertEquals(5, result.size());
+ assertTrue(Sets.newHashSet(result).equals(EAST_LANGUAGES));
+ }
+
+ @Test
+ public void testListLanguages_TwoDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("language", "*", resources));
+ assertEquals(6, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("langdbeast", "langdbwest", "c", "internal", "plpgsql", "sql")));
+ }
+
+ @Test
+ public void testListLanguages_AllDb_AllFilter() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("language", "*", resources));
+ assertEquals(6, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("langdbeast", "langdbwest", "c", "internal", "plpgsql", "sql")));
+ }
+
+ @Test
+ public void testListLanguages_SingleDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("language", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListLanguages_TwoDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("language", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListLanguages_AllDb_FilteredAbsent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("language", "z", resources));
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testListLanguages_SingleDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east"));
+ List<String> result = service.lookupResource(getContext("language", "l", resources));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("langdbeast")));
+ }
+
+ @Test
+ public void testListLanguages_TwoDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("east", "west"));
+ List<String> result = service.lookupResource(getContext("language", "l", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("langdbeast", "langdbwest")));
+ }
+
+ @Test
+ public void testListLanguages_AllDb_FilteredPresent() throws Exception {
+ resources.put("database", Arrays.asList("*"));
+ List<String> result = service.lookupResource(getContext("language", "l", resources));
+ assertEquals(2, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("langdbeast", "langdbwest")));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListProtocolsTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListProtocolsTest.java b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListProtocolsTest.java
new file mode 100644
index 0000000..d46febc
--- /dev/null
+++ b/ranger-plugin/integration/admin/src/test/java/org/apache/hawq/ranger/integration/admin/ListProtocolsTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.hawq.ranger.integration.admin;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ListProtocolsTest extends LookupTestBase {
+
+ private static final Set<String> PROTOCOLS = Sets.newHashSet("file", "ftp", "gpfdist", "gpfdists", "http", "pxf");
+
+ @Test
+ public void testListProtocols_All() throws Exception {
+ List<String> result = service.lookupResource(getContext("protocol", "*"));
+ assertEquals(6, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet(PROTOCOLS)));
+ }
+
+ @Test
+ public void testListProtocols_FilteredPresent() throws Exception {
+ List<String> result = service.lookupResource(getContext("protocol", "h"));
+ assertEquals(1, result.size());
+ assertTrue(Sets.newHashSet(result).equals(Sets.newHashSet("http")));
+ }
+
+ @Test
+ public void testListProtocols_FilteredAbsent() throws Exception {
+ List<String> result = service.lookupResource(getContext("protocol", "z"));
+ assertTrue(result.isEmpty());
+ }
+
+}
[2/4] incubator-hawq git commit: HAWQ-1203. Ranger Plugin Service
Implementation. (with contributions by Lav Jain and Leslie Chang) (close
#1092)
Posted by ad...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/pom.xml b/ranger-plugin/pom.xml
new file mode 100644
index 0000000..20d3112
--- /dev/null
+++ b/ranger-plugin/pom.xml
@@ -0,0 +1,248 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <packaging>pom</packaging>
+ <name>HAWQ Ranger Plugin</name>
+ <description>HAWQ Ranger Plugin</description>
+
+ <modules>
+ <module>admin-plugin</module>
+ <module>service</module>
+ </modules>
+
+ <properties>
+ <jackson.version>1.9</jackson.version>
+ <release.version>1</release.version>
+ <postgresql.version>9.1-901-1.jdbc4</postgresql.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rpm-maven-plugin</artifactId>
+ <version>2.0.1</version>
+ <inherited>false</inherited>
+ <executions>
+ <execution>
+ <inherited>false</inherited>
+ <phase>install</phase>
+ <goals>
+ <goal>rpm</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ <configuration>
+ <copyright>ASL 2.0</copyright>
+ <group>org.apache.hawq.ranger</group>
+ <defaultUsername>gpadmin</defaultUsername>
+ <defaultGroupname>gpadmin</defaultGroupname>
+ <description>
+ HAWQ Ranger plugin.
+ </description>
+ <release>${release.version}</release>
+ <requires>
+ <require>bigtop-tomcat</require>
+ <require>hawq_${hawq.name.version} >= ${project.version}</require>
+ </requires>
+ <mappings>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/bin</directory>
+ <filemode>755</filemode>
+ <sources>
+ <source>
+ <location>scripts</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/lib</directory>
+ <sources>
+ <source>
+ <location>admin-plugin/target/ranger-plugin-admin-${project.version}.jar</location>
+ </source>
+ <source>
+ <location>admin-plugin/target/lib/postgresql-${postgresql.version}.jar</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/etc</directory>
+ <sources>
+ <source>
+ <location>conf/ranger-servicedef-hawq.json</location>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/bin</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/logs</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/temp</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/work</directory>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/webapps</directory>
+ <sources>
+ <source>
+ <location>service/target/ranger-plugin-service-${project.version}.war</location>
+ <destination>rps.war</destination>
+ </source>
+ </sources>
+ </mapping>
+ <mapping>
+ <directory>/usr/local/hawq_${hawq.name.version}/ranger/plugin-service/conf</directory>
+ <sources>
+ <source>
+ <location>conf/tomcat-server.xml</location>
+ </source>
+ </sources>
+ </mapping>
+ </mappings>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <id>regex-property</id>
+ <goals>
+ <goal>regex-property</goal>
+ </goals>
+ <configuration>
+ <name>hawq.name.version</name>
+ <value>${project.version}</value>
+ <regex>^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)?$</regex>
+ <replacement>$1_$2_$3_$4</replacement>
+ <failIfNoMatch>true</failIfNoMatch>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ <version>0.6.0</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>${postgresql.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>11.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/register_hawq.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/register_hawq.sh b/ranger-plugin/scripts/register_hawq.sh
new file mode 100755
index 0000000..11e2df8
--- /dev/null
+++ b/ranger-plugin/scripts/register_hawq.sh
@@ -0,0 +1,217 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+function usage() {
+ echo "USAGE: register_hawq.sh -r ranger_host:ranger_port -u ranger_user -p ranger_password -h hawq_host:hawq_port -w hawq_user -q hawq_password"
+ exit 1
+}
+
+function fail() {
+ echo "ERROR: $1"
+ exit 1
+}
+
+function mask() {
+ printf -v stars '%*s' ${#1} ''
+ echo "[${stars// /*}]"
+}
+
+function read_value() {
+ local input
+ read -p "Enter value for $1 : " input
+ echo $input
+}
+
+function read_password() {
+ local input
+ read -s -p "Enter value for $1 : " input
+ echo $input
+}
+
+function get_ranger_url() {
+ while [[ -z "$RANGER_URL" ]]
+ do
+ RANGER_URL=$(read_value "Ranger Admin host and port (e.g. abc.com:6080)")
+ done
+ local prefix="http://"
+ RANGER_URL=${RANGER_URL#$prefix}
+}
+
+function get_ranger_user() {
+ while [[ -z "$RANGER_USER" ]]
+ do
+ RANGER_USER=$(read_value "Ranger Admin user name")
+ done
+}
+
+function get_ranger_password() {
+ while [[ -z "$RANGER_PASSWORD" ]]
+ do
+ RANGER_PASSWORD=$(read_password "Ranger Admin password")
+ echo
+ done
+}
+
+function get_hawq_url() {
+ #todo read hawq-site.xml ?
+ local default=`hostname -f`
+ default="${default}:5432"
+ while [[ -z "$HAWQ_URL" ]]
+ do
+ HAWQ_URL=$(read_value "HAWQ Master host and port [${default}]")
+ done
+ local prefix="http://"
+ HAWQ_URL=${HAWQ_URL#$prefix}
+ local parts=(${HAWQ_URL//:/ })
+ if [ ${#parts[@]} != 2 ]; then
+ fail "Incorrect value for HAWQ Master host and port."
+ fi
+ HAWQ_HOST=${parts[0]}
+ HAWQ_PORT=${parts[1]}
+}
+
+function get_hawq_user() {
+ local default="gpadmin"
+ while [[ -z "$HAWQ_USER" ]]
+ do
+ HAWQ_USER=$(read_value "HAWQ user name [${default}]")
+ done
+}
+
+function get_hawq_password() {
+ while [[ -z "$HAWQ_PASSWORD" ]]
+ do
+ HAWQ_PASSWORD=$(read_password "HAWQ password")
+ echo
+ done
+}
+
+function parse_params() {
+ while [[ $# -gt 0 ]]
+ do
+ key="$1"
+ case $key in
+ -r)
+ RANGER_URL="$2"
+ shift
+ ;;
+ -u)
+ RANGER_USER="$2"
+ shift
+ ;;
+ -p)
+ RANGER_PASSWORD="$2"
+ shift
+ ;;
+ -h)
+ HAWQ_URL="$2"
+ shift
+ ;;
+ -w)
+ HAWQ_USER="$2"
+ shift
+ ;;
+ -q)
+ HAWQ_PASSWORD="$2"
+ shift
+ ;;
+ *)
+ usage
+ ;;
+ esac
+ shift
+ done
+}
+
+function validate_params() {
+ get_ranger_url
+ get_ranger_user
+ get_ranger_password
+ get_hawq_url
+ get_hawq_user
+ get_hawq_password
+ echo "RANGER URL = ${RANGER_URL}"
+ echo "RANGER User = ${RANGER_USER}"
+ echo "RANGER Password = $(mask ${RANGER_PASSWORD})"
+ echo "HAWQ HOST = ${HAWQ_HOST}"
+ echo "HAWQ PORT = ${HAWQ_PORT}"
+ echo "HAWQ User = ${HAWQ_USER}"
+ echo "HAWQ Password = $(mask ${HAWQ_PASSWORD})"
+}
+
+function check_hawq_service_definition() {
+ echo $(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} http://${RANGER_URL}/service/public/v2/api/servicedef/name/hawq | grep hawq | wc -l)
+}
+
+function create_hawq_service_definition() {
+ if [ $(check_hawq_service_definition) == 0 ]; then
+ local json_file="$(dirname ${SCRIPT_DIR})/etc/ranger-servicedef-hawq.json"
+ if [ ! -f ${json_file} ]; then
+ fail "File ${json_file} not found."
+ fi
+ echo "HAWQ service definition was not found in Ranger Admin, creating it by uploading ${json_file}"
+ local output=$(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} -H "Content-Type: application/json" -X POST http://${RANGER_URL}/service/plugins/definitions -d @${json_file})
+ local created=$(echo ${output} | grep created | wc -l)
+ if [ ${created} == 0 ] || [ $(check_hawq_service_definition) == 0 ]; then
+ fail "Creation of HAWQ service definition from ${json_file} in Ranger Admin at ${RANGER_URL} failed. ${output}"
+ fi
+ else
+ echo "HAWQ service definition already exists in Ranger Admin, nothing to do."
+ fi
+}
+
+function check_hawq_service_instance() {
+ echo $(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} http://${RANGER_URL}/service/public/v2/api/service/name/hawq | grep hawq | wc -l)
+}
+
+function create_hawq_service_instance() {
+ if [ $(check_hawq_service_instance) == 0 ]; then
+ local payload="{\"name\":\"hawq\",
+ \"type\":\"hawq\",
+ \"description\":\"HAWQ Master\",
+ \"isEnabled\":true,
+ \"configs\":{\"username\":\"${HAWQ_USER}\",
+ \"password\":\"${HAWQ_PASSWORD}\",
+ \"hostname\":\"${HAWQ_HOST}\",
+ \"port\":\"${HAWQ_PORT}\"}}"
+
+ echo "HAWQ service instance was not found in Ranger Admin, creating it."
+ local output=$(curl -sS -u ${RANGER_USER}:${RANGER_PASSWORD} -H "Content-Type: application/json" -X POST http://${RANGER_URL}/service/public/v2/api/service -d "${payload}")
+ local created=$(echo ${output} | grep created | wc -l)
+ if [ ${created} == 0 ] || [ $(check_hawq_service_instance) == 0 ]; then
+ fail "Creation of HAWQ service instance in Ranger Admin at ${RANGER_URL} failed. ${output}"
+ fi
+ else
+ echo "HAWQ service instance already exists in Ranger Admin, nothing to do."
+ fi
+}
+
+main() {
+ if [[ $# -lt 1 ]]; then
+ usage
+ fi
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ parse_params "$@"
+ validate_params
+ create_hawq_service_definition
+ create_hawq_service_instance
+}
+main "$@"
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/rps.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/rps.sh b/ranger-plugin/scripts/rps.sh
new file mode 100755
index 0000000..e8ccf3a
--- /dev/null
+++ b/ranger-plugin/scripts/rps.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+if [ $# -le 0 ]; then
+ echo "Usage: rps (start|stop|init) [<catalina-args...>]"
+ exit 1
+fi
+
+actionCmd=$1
+shift
+
+CWDIR=$( cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
+source $CWDIR/rps_env.sh
+
+setup_rps() {
+ echo "Initializing Hawq Ranger Plugin Service..."
+ cp $CATALINA_HOME/conf.template/* $CATALINA_BASE/conf
+ cp $CATALINA_BASE/conf/tomcat-server.xml $CATALINA_BASE/conf/server.xml
+ pushd $CATALINA_BASE/webapps >/dev/null
+ unzip -d rps rps.war >/dev/null
+ find . -name ranger-hawq-security.xml | xargs sed -i \
+ "s/localhost:6080/$RANGER_ADMIN_HOST:$RANGER_ADMIN_PORT/g"
+ popd >/dev/null
+ echo "Hawq Ranger Plugin Service installed on http://$RPS_HOST:$RPS_PORT/rps"
+ echo "Please use 'rps.sh start' to start the service"
+}
+
+case $actionCmd in
+ (init)
+ setup_rps
+ ;;
+ (start)
+ $CATALINA_HOME/bin/catalina.sh start "$@"
+ echo "Waiting for RPS service to start..."
+ sleep 15
+ ;;
+ (stop)
+ $CATALINA_HOME/bin/catalina.sh stop "$@"
+ echo "Waiting for RPS service to stop..."
+ sleep 10
+ ;;
+esac
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/scripts/rps_env.sh
----------------------------------------------------------------------
diff --git a/ranger-plugin/scripts/rps_env.sh b/ranger-plugin/scripts/rps_env.sh
new file mode 100755
index 0000000..ae36e8f
--- /dev/null
+++ b/ranger-plugin/scripts/rps_env.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+export CATALINA_HOME=/usr/lib/bigtop-tomcat
+export CATALINA_BASE=/usr/local/hawq/ranger/plugin-service
+
+export RANGER_ADMIN_HOST=${RANGER_ADMIN_HOST:-localhost}
+export RANGER_ADMIN_PORT=${RANGER_ADMIN_PORT:-6080}
+
+export RPS_HOST=${RPS_HOST:-localhost}
+export RPS_PORT=${RPS_PORT:-8432}
+export CATALINA_OPTS="-Dhttp.host=$RPS_HOST -Dhttp.port=$RPS_PORT"
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/pom.xml b/ranger-plugin/service/pom.xml
new file mode 100644
index 0000000..3f2f9f8
--- /dev/null
+++ b/ranger-plugin/service/pom.xml
@@ -0,0 +1,88 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin-service</artifactId>
+ <packaging>war</packaging>
+ <name>HAWQ Ranger Service</name>
+ <description>HAWQ Ranger Service</description>
+ <parent>
+ <groupId>org.apache.hawq</groupId>
+ <artifactId>ranger-plugin</artifactId>
+ <version>2.1.0.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <!-- use mvn tomcat6:run-war to run the appserver with the app deployed -->
+ <groupId>org.apache.tomcat.maven</groupId>
+ <artifactId>tomcat6-maven-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <path>/rps</path>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.ranger</groupId>
+ <artifactId>ranger-plugins-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
new file mode 100644
index 0000000..625ce50
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/HawqAuthorizer.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+
+/**
+ * Interface for making authorization decisions.
+ */
+public interface HawqAuthorizer {
+
+ /**
+ * Determines whether access should be allowed for the given authorization request.
+ * @param request authorization request
+ * @return authorization response
+ */
+ AuthorizationResponse isAccessAllowed(AuthorizationRequest request);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
new file mode 100644
index 0000000..04d6f99
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java
@@ -0,0 +1,263 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+import org.apache.hawq.ranger.authorization.model.HawqPrivilege;
+import org.apache.hawq.ranger.authorization.model.HawqResource;
+import org.apache.hawq.ranger.authorization.model.ResourceAccess;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.hawq.ranger.authorization.Utils.HAWQ;
+
+/**
+ * Authorizer implementation that uses Ranger to make access decision. Implemented as a singleton.
+ */
+public class RangerHawqAuthorizer implements HawqAuthorizer {
+
+ private static final Log LOG = LogFactory.getLog(RangerHawqAuthorizer.class);
+
+ private static final RangerHawqAuthorizer INSTANCE = new RangerHawqAuthorizer();
+
+ private RangerBasePlugin rangerPlugin;
+
+ /**
+ * Returns the instance of the RangerHawqAuthorizer.
+ * @return the singleton instance
+ */
+ public static RangerHawqAuthorizer getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Constructor. Initializes Ranger Base Plugin to fetch policies from Ranger.
+ */
+ private RangerHawqAuthorizer() {
+
+ LOG.info("Initializing RangerHawqAuthorizer");
+
+ String appId = Utils.getAppId();
+
+ LOG.info(String.format("Initializing RangerBasePlugin for service %s:%s", HAWQ, appId));
+ rangerPlugin = new RangerBasePlugin(HAWQ, appId);
+ rangerPlugin.init();
+ LOG.info(String.format("Initialized RangerBasePlugin for service %s:%s", HAWQ, appId));
+ }
+
+ @Override
+ public AuthorizationResponse isAccessAllowed(AuthorizationRequest request) {
+
+ // validate request to make sure no data is missing
+ validateRequest(request);
+
+ // prepare response object
+ AuthorizationResponse response = new AuthorizationResponse();
+ response.setRequestId(request.getRequestId());
+ Set<ResourceAccess> access = new HashSet<>();
+ response.setAccess(access);
+
+ // iterate over resource requests, augment processed ones with the decision and add to the response
+ for (ResourceAccess resourceAccess : request.getAccess()) {
+ boolean accessAllowed = authorizeResource(resourceAccess, request.getUser());
+ resourceAccess.setAllowed(accessAllowed);
+ access.add(resourceAccess);
+ }
+
+ return response;
+ }
+
+ /**
+ * Authorizes access to a single resource for a given user.
+ *
+ * @param resourceAccess resource to authorize access to
+ * @param user user requesting authorization
+ * @return true if access is authorized, false otherwise
+ */
+ private boolean authorizeResource(ResourceAccess resourceAccess, String user) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Request: access for user=%s to resource=%s with privileges=%s",
+ user, resourceAccess.getResource(), resourceAccess.getPrivileges()));
+ }
+
+ RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl();
+ //resource.setOwnerUser();
+ for (Map.Entry<HawqResource, String> resourceEntry : resourceAccess.getResource().entrySet()) {
+ rangerResource.setValue(resourceEntry.getKey().name(), resourceEntry.getValue());
+ }
+
+ boolean accessAllowed = true;
+ // iterate over all privileges requested
+ for (HawqPrivilege privilege : resourceAccess.getPrivileges()) {
+ // TODO not clear how we will get user groups -- Kerberos case ?
+ Set<String> userGroups = Collections.emptySet();
+ boolean privilegeAuthorized = authorizeResourcePrivilege(rangerResource, privilege.name(), user, userGroups);
+ // ALL model of evaluation -- all privileges must be authorized for access to be allowed
+ if (!privilegeAuthorized) {
+ accessAllowed = false;
+ break; // terminate early if even a single privilege is not authorized
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Decision: accessAllowed=%s for user=%s to resource=%s with privileges=%s",
+ accessAllowed, user, resourceAccess.getResource(), resourceAccess.getPrivileges()));
+ }
+
+ return accessAllowed;
+ }
+
+ /**
+ * Authorizes access of a given type (privilege) to a single resource for a given user.
+ *
+ * @param rangerResource resource to authorize access to
+ * @param accessType privilege requested for a given resource
+ * @param user user requesting authorization
+ * @param userGroups groups a user belongs to
+ * @return true if access is authorized, false otherwise
+ */
+ private boolean authorizeResourcePrivilege(RangerAccessResource rangerResource, String accessType, String user, Set<String> userGroups) {
+
+ Map<String, String> resourceMap = rangerResource.getAsMap();
+ String database = resourceMap.get(HawqResource.database.name());
+ String schema = resourceMap.get(HawqResource.schema.name());
+ int resourceSize = resourceMap.size();
+
+ // special handling for non-leaf policies
+ if (accessType.equals(HawqPrivilege.create.name()) && database != null && schema == null && resourceSize == 1) {
+ accessType = HawqPrivilege.create_schema.toValue();
+ LOG.debug("accessType mapped to: create-schema");
+ } else if (accessType.equals(HawqPrivilege.usage.name()) && database != null && schema != null && resourceSize == 2) {
+ accessType = HawqPrivilege.usage_schema.toValue();
+ LOG.debug("accessType mapped to: usage-schema");
+ }
+
+ RangerAccessRequest rangerRequest = new RangerAccessRequestImpl(rangerResource, accessType, user, userGroups);
+ RangerAccessResult result = rangerPlugin.isAccessAllowed(rangerRequest);
+ boolean accessAllowed = result != null && result.getIsAllowed();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("--- RangerDecision: accessAllowed=%s for user=%s to resource=%s with privileges=%s, result present=%s",
+ accessAllowed, user, rangerResource.getAsString(), accessType, result!=null));
+ }
+
+ return accessAllowed;
+ }
+
+ /**
+ * Validates that authorization requests do not have any missing data.
+ *
+ * @param request authorization request
+ * @throws IllegalArgumentException if any data is missing
+ */
+ private void validateRequest(AuthorizationRequest request) {
+ LOG.debug("Validating authorization request");
+
+ if (request == null) {
+ throw new IllegalArgumentException("request is null");
+ }
+
+ if (request.getRequestId() == null) {
+ throw new IllegalArgumentException("requestId field is missing or null in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getUser())) {
+ throw new IllegalArgumentException("user field is missing or empty in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getClientIp())) {
+ throw new IllegalArgumentException("clientIp field is missing or empty in the request");
+ }
+
+ if (StringUtils.isEmpty(request.getContext())) {
+ throw new IllegalArgumentException("context field is missing or empty in the request");
+ }
+
+ Set<ResourceAccess> accessSet = request.getAccess();
+ if (CollectionUtils.isEmpty(accessSet)) {
+ throw new IllegalArgumentException("access field is missing or empty in the request");
+ }
+
+ for (ResourceAccess access : accessSet) {
+ validateResourceAccess(access);
+ }
+
+ LOG.debug("Successfully validated authorization request");
+ }
+
+ /**
+ * Validates that resource access does not have any missing data.
+ *
+ * @param access resource access data
+ * @throws IllegalArgumentException if any data is missing
+ */
+ private void validateResourceAccess(ResourceAccess access) {
+ Map<HawqResource, String> resourceMap = access.getResource();
+ if (MapUtils.isEmpty(resourceMap)) {
+ throw new IllegalArgumentException("resource field is missing or empty in the request");
+ }
+ for (Map.Entry<HawqResource, String> resourceEntry : resourceMap.entrySet()) {
+ if (StringUtils.isEmpty(resourceEntry.getValue())) {
+ throw new IllegalArgumentException(
+ String.format("resource value is missing for key=%s in the request", resourceEntry.getKey())
+ );
+ }
+ }
+ if (CollectionUtils.isEmpty(access.getPrivileges())) {
+ throw new IllegalArgumentException("set of privileges is missing empty in the request");
+ }
+ }
+
+
+
+ /**
+ * Sets an instance of the Ranger Plugin for testing.
+ *
+ * @param plugin plugin instance to use while testing
+ */
+ void setRangerPlugin(RangerBasePlugin plugin) {
+ rangerPlugin = plugin;
+ }
+
+ /**
+ * Returns the instance of the Ranger Plugin for testing.
+ *
+ * @return BaseRangerPlugin instance
+ */
+ RangerBasePlugin getRangerPlugin() {
+ return rangerPlugin;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
new file mode 100644
index 0000000..26a7660
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqPluginResource.java
@@ -0,0 +1,86 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import com.sun.jersey.spi.resource.Singleton;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hawq.ranger.authorization.model.AuthorizationRequest;
+import org.apache.hawq.ranger.authorization.model.AuthorizationResponse;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.Date;
+
+/**
+ * JAX-RS resource for the authorization endpoint.
+ */
+@Path("/")
+@Singleton
+public class RangerHawqPluginResource {
+
+ private static final Log LOG = LogFactory.getLog(RangerHawqPluginResource.class);
+
+ private HawqAuthorizer authorizer;
+ private String version;
+
+ /**
+ * Constructor. Creates a new instance of the resource that uses <code>RangerHawqAuthorizer</code>.
+ */
+ public RangerHawqPluginResource() {
+ this.authorizer = RangerHawqAuthorizer.getInstance();
+ }
+
+
+ @Path("/version")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response version()
+ {
+ String output = "{\"version\":\"" + Utils.getVersion() + "\"}";
+ return Response.status(200).entity(output).build();
+ }
+
+ /**
+ * Authorizes a request to access protected resources with requested privileges.
+ * @param request authorization request
+ * @return authorization response
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public AuthorizationResponse authorize(AuthorizationRequest request)
+ {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Received authorization request: " + request);
+ }
+
+ // exceptions are handled by ServiceExceptionMapper
+ AuthorizationResponse response = authorizer.isAccessAllowed(request);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Returning authorization response: " + response);
+ }
+ return response;
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
new file mode 100644
index 0000000..b983d72
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/ServiceExceptionMapper.java
@@ -0,0 +1,97 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Maps service exceptions to HTTP response.
+ */
+@Provider
+public class ServiceExceptionMapper implements ExceptionMapper<Throwable> {
+
+ private static final Log LOG = LogFactory.getLog(ServiceExceptionMapper.class);
+
+ @Override
+ public Response toResponse(Throwable e) {
+
+ LOG.error("Service threw an exception: ", e);
+
+ // default to internal server error (HTTP 500)
+ Response.Status status = Response.Status.INTERNAL_SERVER_ERROR;
+
+ if (e instanceof IllegalArgumentException) {
+ status = Response.Status.BAD_REQUEST;
+ }
+
+ ErrorPayload error = new ErrorPayload(status.getStatusCode(), e.getMessage());
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Returning error response: status=%s message=%s",
+ error.getStatus(), error.getMessage()));
+ }
+
+ return Response.status(status)
+ .entity(error)
+ .type(MediaType.APPLICATION_JSON)
+ .build();
+ }
+
+ /**
+ * Represents payload to be serialized as JSON into response.
+ */
+ public static class ErrorPayload {
+ private int status;
+ private String message;
+
+ /**
+ * Constructor.
+ * @param status HTTP error status
+ * @param message error message
+ */
+ public ErrorPayload(int status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ /**
+ * Returns status code
+ * @return status code
+ */
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * Returns error message
+ * @return error message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
new file mode 100644
index 0000000..86f7fc4
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/Utils.java
@@ -0,0 +1,80 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Utility class for reading values from the property file.
+ */
+public abstract class Utils {
+
+ public static final String HAWQ = "hawq";
+ public static final String UNKNOWN = "unknown";
+ public static final String APP_ID_PROPERTY = "ranger.hawq.instance";
+ public static final String VERSION_PROPERTY = "version";
+ public static final String RANGER_SERVICE_PROPERTY_FILE = "rps.properties";
+
+ private static final Log LOG = LogFactory.getLog(Utils.class);
+ private static final Properties properties = readPropertiesFromFile();
+
+ /**
+ * Retrieves the app id from the environment variable with the key ranger.hawq.instance
+ * or from the rps.properties file with the key ranger.hawq.instance
+ *
+ * If none exist, hawq is used as the default
+ *
+ * @return String id of the app
+ */
+ public static String getAppId() {
+ return System.getProperty(APP_ID_PROPERTY, properties.getProperty(APP_ID_PROPERTY, HAWQ));
+ }
+
+ /**
+ * Retrieves the version read from the property file.
+ *
+ * If none exist, unknown is used as the default
+ *
+ * @return version of the service
+ */
+ public static String getVersion() {
+ return properties.getProperty(VERSION_PROPERTY, UNKNOWN);
+ }
+
+ /**
+ * Reads properties from the property file.
+ * @return properties read from the file
+ */
+ private static Properties readPropertiesFromFile() {
+ Properties prop = new Properties();
+ InputStream inputStream = Utils.class.getClassLoader().getResourceAsStream(RANGER_SERVICE_PROPERTY_FILE);
+ try {
+ prop.load(inputStream);
+ } catch (IOException e) {
+ LOG.error("Failed to read from: " + RANGER_SERVICE_PROPERTY_FILE);
+ }
+ return prop;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
new file mode 100644
index 0000000..6e8ab4f
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationRequest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import java.util.Set;
+
+/**
+ * Model for submitting an authorization request for multiple resources.
+ */
+public class AuthorizationRequest {
+
+ private Integer requestId;
+ private String user;
+ private String clientIp;
+ private String context;
+ private Set<ResourceAccess> access;
+
+ /**
+ * Returns request id.
+ * @return id of the request
+ */
+ public Integer getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets request id.
+ * @param requestId id of the request
+ */
+ public void setRequestId(Integer requestId) {
+ this.requestId = requestId;
+ }
+
+ /**
+ * Returns user name for the user submitting the access request.
+ * @return name of the user
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * Sets user name for the user submitting the access request.
+ * @param user name of the user
+ */
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ /**
+ * Returns IP address of the client where the user request is made from.
+ * @return IP address of the user's client
+ */
+ public String getClientIp() {
+ return clientIp;
+ }
+
+ /**
+ * Sets IP address of the client where the user request is made from.
+ * @param clientIp IP address of the user's client
+ */
+ public void setClientIp(String clientIp) {
+ this.clientIp = clientIp;
+ }
+
+ /**
+ * Returns context of the request, usually a SQL query that the user ran
+ * @return context of the request
+ */
+ public String getContext() {
+ return context;
+ }
+
+ /**
+ * Sets the context of the request, usually a SQL query that the user ran
+ * @param context context of the request
+ */
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ /**
+ * Returns a set of <code>ResourceAccess</code> objects.
+ * @return s set of <code>ResourceAccess</code> objects
+ */
+ public Set<ResourceAccess> getAccess() {
+ return access;
+ }
+
+ /**
+ * Sets <code>ResourceAccess</code> objects
+ * @param access a set of <code>ResourceAccess</code> objects
+ */
+ public void setAccess(Set<ResourceAccess> access) {
+ this.access = access;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
new file mode 100644
index 0000000..f989b8d
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/AuthorizationResponse.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import java.util.Set;
+
+/**
+ * Model for response containing authorization decisions for access to multiple resources.
+ */
+public class AuthorizationResponse {
+
+ private Integer requestId;
+ private Set<ResourceAccess> access;
+
+ /**
+ * Returns request id.
+ * @return id of the request
+ */
+ public Integer getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets request id.
+ * @param requestId id of the request
+ */
+ public void setRequestId(Integer requestId) {
+ this.requestId = requestId;
+ }
+
+ /**
+ * Returns a set of <code>ResourceAccess</code> objects.
+ * @return a set of <code>ResourceAccess</code> objects
+ */
+ public Set<ResourceAccess> getAccess() {
+ return access;
+ }
+
+ /**
+ * Sets <code>ResourceAccess</code> objects
+ * @param access a set of <code>ResourceAccess</code> objects
+ */
+ public void setAccess(Set<ResourceAccess> access) {
+ this.access = access;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
new file mode 100644
index 0000000..ffce67a
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqPrivilege.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Model enumeration of types of HAWQ privileges.
+ */
+public enum HawqPrivilege {
+ select,
+ insert,
+ update,
+ delete,
+ references,
+ usage,
+ create,
+ connect,
+ execute,
+ temp,
+ create_schema,
+ usage_schema,
+ all;
+
+ /**
+ * Returns HawqPrivilege type by case-insensitive lookup of the value.
+ * @param key case insensitive string representation of the privilege
+ * @return instance of HawqPrivilege
+ */
+ @JsonCreator
+ public static HawqPrivilege fromString(String key) {
+ return key == null ? null : HawqPrivilege.valueOf(key.replace('-', '_').toLowerCase());
+ }
+
+ /**
+ * Returns string representation of the enum, replaces underscores with dashes.
+ * @return string representation of the enum
+ */
+ @JsonValue
+ public String toValue() {
+ return name().replace('_', '-');
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
new file mode 100644
index 0000000..c9de4e7
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/HawqResource.java
@@ -0,0 +1,46 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+
+/**
+ * Model enumeration of types of HAWQ resources.
+ */
+public enum HawqResource {
+ database,
+ schema,
+ table,
+ sequence,
+ function,
+ language,
+ tablespace,
+ protocol;
+
+ /**
+ * Returns HawqResource type by case-insensitive lookup of the value.
+ * @param key case insensitive string representation of the resource
+ * @return instance of HawqResource
+ */
+ @JsonCreator
+ public static HawqResource fromString(String key) {
+ return key == null ? null : HawqResource.valueOf(key.toLowerCase());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
new file mode 100644
index 0000000..df1631a
--- /dev/null
+++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/model/ResourceAccess.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hawq.ranger.authorization.model;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Model object for requesting access to a single resource.
+ */
+public class ResourceAccess {
+
+ private Map<HawqResource, String> resource;
+ private Set<HawqPrivilege> privileges;
+ private boolean allowed = false;
+
+ public Set<HawqPrivilege> getPrivileges() {
+ return privileges;
+ }
+
+ public void setPrivileges(Set<HawqPrivilege> privileges) {
+ this.privileges = privileges;
+ }
+
+ public boolean isAllowed() {
+ return allowed;
+ }
+
+ public void setAllowed(boolean allowed) {
+ this.allowed = allowed;
+ }
+
+ public Map<HawqResource, String> getResource() {
+ return resource;
+ }
+
+ public void setResource(Map<HawqResource, String> resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("resource", resource)
+ .append("privileges", privileges)
+ .append("allowed", allowed)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResourceAccess that = (ResourceAccess) o;
+ return allowed == that.allowed &&
+ Objects.equals(resource, that.resource) &&
+ Objects.equals(privileges, that.privileges);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(resource, privileges, allowed);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/log4j.properties b/ranger-plugin/service/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6bbdaed
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/log4j.properties
@@ -0,0 +1,42 @@
+# 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.
+
+# see debug messages during unit tests
+project.root.logger=DEBUG,console
+
+# suppress all logging output during unit tests
+#project.root.logger=FATAL,devnull
+
+#
+# Loggers
+#
+log4j.rootLogger=${project.root.logger}
+
+# ignore most errors from the Apache Ranger and Hadoop for unit tests
+log4j.logger.org.apache.ranger=FATAL
+log4j.logger.org.apache.hadoop=FATAL
+
+#
+# Appenders
+#
+
+# nothing
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+
+# console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
new file mode 100644
index 0000000..46dd75d
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/ranger-hawq-security.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+
+<!--
+ 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.
+-->
+
+<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
+ <property>
+ <name>ranger.plugin.hawq.service.name</name>
+ <value>hawq</value>
+ <description>
+ Name of the Ranger service containing policies for this HAWQ instance
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.source.impl</name>
+ <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
+ <description>
+ Class to retrieve policies from the source
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.url</name>
+ <value>http://localhost:6080</value>
+ <description>
+ URL to Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.ssl.config.file</name>
+ <value>/usr/local/hawq/ranger/etc/ranger-policymgr-ssl.xml</value>
+ <description>
+ Path to the file containing SSL details to contact Ranger Admin
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.pollIntervalMs</name>
+ <value>30000</value>
+ <description>
+ How often to poll for changes in policies?
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.cache.dir</name>
+ <value>/usr/local/hawq/ranger/policycache</value>
+ <description>
+ Directory where Ranger policies are cached after successful retrieval from the source
+ </description>
+ </property>
+
+ <!--
+ <property>
+ <name>xasecure.hive.update.xapolicies.on.grant.revoke</name>
+ <value>true</value>
+ <description>Should Hive plugin update Ranger policies for updates to permissions done using GRANT/REVOKE?</description>
+ </property>
+ -->
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.client.connection.timeoutMs</name>
+ <value>120000</value>
+ <description>
+ RangerRESTClient Connection Timeout in Milliseconds
+ </description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.hawq.policy.rest.client.read.timeoutMs</name>
+ <value>30000</value>
+ <description>
+ RangerRESTClient read Timeout in Milliseconds
+ </description>
+ </property>
+</configuration>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/resources/rps.properties
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/resources/rps.properties b/ranger-plugin/service/src/main/resources/rps.properties
new file mode 100644
index 0000000..9e2b1f4
--- /dev/null
+++ b/ranger-plugin/service/src/main/resources/rps.properties
@@ -0,0 +1,17 @@
+# 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.
+
+ranger.hawq.instance=hawq
+version=${project.version}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..36c976f
--- /dev/null
+++ b/ranger-plugin/service/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<!--
+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.
+-->
+
+<web-app version="3.0"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+
+ <!--
+ This is the HAWQ Ranger Plugin Service webapp xml descriptor
+
+ servlet-class Jersey entrypoint class
+ init-param com.sun.jersey.config.property.packages
+ Tells Jersey where are the REST components of this webapp
+ jersey.config.server.provider.scanning.recursive
+ Tells Jersey to recusively scan package for REST resources
+ load-on-startup Initialize the webapp on app server startup
+ servlet-mapping Maps the path of the servlet (ranger-plugin/*)
+ listener A class called after the webapp was initialized and before it's about to go down
+ -->
+
+ <servlet>
+ <servlet-name>HAWQ_Ranger_Plugin_Service</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.packages</param-name>
+ <param-value>org.apache.hawq.ranger.authorization</param-value>
+ </init-param>
+ <init-param>
+ <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>HAWQ_Ranger_Plugin_Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <!--
+ <listener>
+ <listener-class>org.apache.hawq.pxf.service.rest.ServletLifecycleListener</listener-class>
+ </listener>
+ -->
+ <!-- log4j configuration
+ Log4jConfigListener looks for a file under log4jConfigLocation.
+ When not using absolute path, the path starts from the webapp root directory.
+ If this file cannot be read, log4j will revert to using the default
+ pxf-log4j.properties inside the webapp. -->
+ <context-param>
+ <param-name>log4jConfigLocation</param-name>
+ <param-value>/etc/pxf/conf/pxf-log4j.properties</param-value>
+ </context-param>
+</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f36b35b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
----------------------------------------------------------------------
diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
new file mode 100644
index 0000000..461864e
--- /dev/null
+++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerAppIdTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hawq.ranger.authorization;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Utils.class)
+public class RangerHawqAuthorizerAppIdTest {
+
+ @Test
+ public void testAppIdIsSet() {
+ PowerMockito.mockStatic(Utils.class);
+ when(Utils.getAppId()).thenReturn("foo");
+ assertEquals("foo", RangerHawqAuthorizer.getInstance().getRangerPlugin().getAppId());
+ }
+}