http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java index 180f9dc,0000000..1f6496b mode 100644,000000..100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayDeployFuncTest.java @@@ -1,337 -1,0 +1,315 @@@ +/** + * 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.knox.gateway; + +import com.jayway.restassured.response.Response; +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; +import org.apache.commons.io.FileUtils; +import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.hadoop.test.TestUtils; +import org.apache.hadoop.test.category.ReleaseTest; +import org.apache.http.HttpStatus; +import org.apache.log4j.Appender; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; - import java.io.InputStream; - import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Pattern; + +import static com.jayway.restassured.RestAssured.given; +import static org.apache.hadoop.test.TestUtils.LOG_ENTER; +import static org.apache.hadoop.test.TestUtils.LOG_EXIT; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertThat; + +@Category(ReleaseTest.class) +public class GatewayDeployFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayDeployFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger( GatewayDeployFuncTest.class ); + + public static Enumeration<Appender> appenders; + public static GatewayConfig config; + public static GatewayServer gateway; + public static File gatewayHome; + public static String gatewayUrl; + public static String clusterUrl; + private static GatewayTestDriver driver = new GatewayTestDriver(); + + @BeforeClass + public static void setupSuite() throws Exception { + LOG_ENTER(); + //appenders = NoOpAppender.setUp(); + driver.setupLdap(0); + LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + LOG_ENTER(); + driver.cleanup(); + //FileUtils.deleteQuietly( new File( config.getGatewayHomeDir() ) ); + //NoOpAppender.tearDown( appenders ); + LOG_EXIT(); + } + + @Before + public void setupGateway() throws Exception { + + File targetDir = new File( System.getProperty( "user.dir" ), "target" ); + File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); + gatewayDir.mkdirs(); + gatewayHome = gatewayDir; + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); + + File topoDir = new File( testConfig.getGatewayTopologyDir() ); + topoDir.mkdirs(); + + File deployDir = new File( testConfig.getGatewayDeploymentDir() ); + deployDir.mkdirs(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String,String> options = new HashMap<>(); + options.put( "persist-master", "false" ); + options.put( "master", "password" ); + try { + srvcs.init( testConfig, options ); + } catch ( ServiceLifecycleException e ) { + e.printStackTrace(); // I18N not required. + } + gateway = GatewayServer.startGateway( testConfig, srvcs ); + MatcherAssert.assertThat( "Failed to start gateway.", gateway, notNullValue() ); + + LOG.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/test-cluster"; + } + + @After + public void cleanupGateway() throws Exception { + gateway.stop(); + FileUtils.deleteQuietly( gatewayHome ); + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( driver.getLdapUrl() ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent() + .addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + .addTag( "provider" ) + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + return xml; + } + - public static InputStream getResourceStream( String resource ) throws IOException { - return getResourceUrl( resource ).openStream(); - } - - public static URL getResourceUrl( String resource ) { - URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); - assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); - return url; - } - - public static String getResourceName( String resource ) { - return getResourceBaseName() + resource; - } - - public static String getResourceBaseName() { - return RESOURCE_BASE_CLASS.getName().replaceAll( "\\.", "/" ) + "/"; - } - + //@Test + public void waitForManualTesting() throws IOException { + System.in.read(); + } + + @Test( timeout = TestUtils.LONG_TIMEOUT ) + public void testDeployRedeployUndeploy() throws InterruptedException, IOException { + LOG_ENTER(); + long sleep = 200; + int numFilesInWebInf = 4; // # files in WEB-INF (ie gateway.xml, rewrite.xml, shiro.ini, web.xml) + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + long topoTimestampBefore, topoTimestampAfter; + + File topoDir = new File( config.getGatewayTopologyDir() ); + File deployDir = new File( config.getGatewayDeploymentDir() ); + File earDir; + + // Make sure deployment directory is empty. + assertThat( topoDir.listFiles().length, is( 0 ) ); + assertThat( deployDir.listFiles().length, is( 0 ) ); + + File descriptor = writeTestTopology( "test-cluster", createTopology() ); + long writeTime = System.currentTimeMillis(); + + earDir = waitForFiles( deployDir, "test-cluster\\.topo\\.[0-9A-Fa-f]+", 1, 0, sleep ); + File warDir = new File( earDir, "%2F" ); + File webInfDir = new File( warDir, "WEB-INF" ); + waitForFiles( webInfDir, ".*", numFilesInWebInf, 0, sleep ); + waitForAccess( serviceUrl, username, password, sleep ); + + // Wait to make sure a second has passed to ensure the the file timestamps are different. + waitForElapsed( writeTime, 1000, 100 ); + + // Redeploy and make sure the timestamp is updated. + topoTimestampBefore = descriptor.lastModified(); + GatewayServer.redeployTopologies( null ); + writeTime = System.currentTimeMillis(); + topoTimestampAfter = descriptor.lastModified(); + assertThat( topoTimestampAfter, greaterThan( topoTimestampBefore ) ); + + // Check to make sure there are two war directories with the same root. + earDir = waitForFiles( deployDir, "test-cluster\\.topo\\.[0-9A-Fa-f]+", 2, 1, sleep ); + warDir = new File( earDir, "%2F" ); + webInfDir = new File( warDir, "WEB-INF" ); + waitForFiles( webInfDir, ".*", numFilesInWebInf, 0, sleep ); + waitForAccess( serviceUrl, username, password, sleep ); + + // Wait to make sure a second has passed to ensure the the file timestamps are different. + waitForElapsed( writeTime, 1000, 100 ); + + // Redeploy and make sure the timestamp is updated. + topoTimestampBefore = descriptor.lastModified(); + GatewayServer.redeployTopologies( "test-cluster" ); + writeTime = System.currentTimeMillis(); + topoTimestampAfter = descriptor.lastModified(); + assertThat( topoTimestampAfter, greaterThan( topoTimestampBefore ) ); + + // Check to make sure there are two war directories with the same root. + earDir = waitForFiles( deployDir, "test-cluster\\.topo\\.[0-9A-Fa-f]+", 3, 2, sleep ); + warDir = new File( earDir, "%2F" ); + webInfDir = new File( warDir, "WEB-INF" ); + waitForFiles( webInfDir, ".*", numFilesInWebInf, 0, sleep ); + waitForAccess( serviceUrl, username, password, sleep ); + + // Delete the test topology. + assertThat( "Failed to delete the topology file.", descriptor.delete(), is( true ) ); + + // Wait to make sure a second has passed to ensure the the file timestamps are different. + waitForElapsed( writeTime, 1000, 100 ); + + waitForFiles( deployDir, ".*", 0, -1, sleep ); + + // Wait a bit more to make sure undeployment finished. + Thread.sleep( sleep ); + + // Make sure the test topology is not accessible. + given().auth().preemptive().basic( username, password ) + .expect().statusCode( HttpStatus.SC_NOT_FOUND ) + .when().get( serviceUrl ); + + // Make sure deployment directory is empty. + assertThat( topoDir.listFiles().length, is( 0 ) ); + assertThat( deployDir.listFiles().length, is( 0 ) ); + LOG_EXIT(); + } + + private void waitForElapsed( long from, long total, long sleep ) throws InterruptedException { + while( System.currentTimeMillis() - from < total ) { + Thread.sleep( sleep ); + } + } + + private File writeTestTopology( String name, XMLTag xml ) throws IOException { + // Create the test topology. + File tempFile = new File( config.getGatewayTopologyDir(), name + ".xml." + UUID.randomUUID() ); + FileOutputStream stream = new FileOutputStream( tempFile ); + xml.toStream( stream ); + stream.close(); + File descriptor = new File( config.getGatewayTopologyDir(), name + ".xml" ); + tempFile.renameTo( descriptor ); + return descriptor; + } + + private File waitForFiles( File dir, String pattern, int count, int index, long sleep ) throws InterruptedException { + RegexDirFilter filter = new RegexDirFilter( pattern ); + while( true ) { + File[] files = dir.listFiles( filter ); + if( files.length == count ) { + return ( index < 0 ) ? null : files[ index ]; + } + Thread.sleep( sleep ); + } + } + + private void waitForAccess( String url, String username, String password, long sleep ) throws InterruptedException { + while( true ) { + Response response = given() + .auth().preemptive().basic( username, password ) + .when().get( url ).andReturn(); + if( response.getStatusCode() == HttpStatus.SC_NOT_FOUND ) { + Thread.sleep( sleep ); + continue; + } + assertThat( response.getContentType(), containsString( "text/plain" ) ); + assertThat( response.getBody().asString(), is( "test-service-response" ) ); + break; + } + } + + private class RegexDirFilter implements FilenameFilter { + + Pattern pattern; + + RegexDirFilter( String regex ) { + pattern = Pattern.compile( regex ); + } + + @Override + public boolean accept( File dir, String name ) { + return pattern.matcher( name ).matches(); + } + } + +}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayHealthFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayHealthFuncTest.java index dfd7ab3,0000000..607ef9a mode 100644,000000..100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayHealthFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayHealthFuncTest.java @@@ -1,229 -1,0 +1,205 @@@ +/** + * 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.knox.gateway; + +import com.jayway.restassured.path.json.JsonPath; +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; +import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.hadoop.test.TestUtils; +import org.apache.http.HttpStatus; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.MediaType; +import java.io.File; +import java.io.FileOutputStream; - import java.io.IOException; - import java.io.InputStream; - import java.net.URL; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +import static com.jayway.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.notNullValue; - import static org.junit.Assert.assertThat; + +public class GatewayHealthFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayAdminFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger(GatewayAdminFuncTest.class); + + public static GatewayConfig config; + public static GatewayServer gateway; + public static String gatewayUrl; + public static String clusterUrl; + public static SimpleLdapDirectoryServer ldap; + public static TcpTransport ldapTransport; + + @BeforeClass + public static void setupSuite() throws Exception { + TestUtils.LOG_ENTER(); + setupLdap(); + setupGateway(); + TestUtils.LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + TestUtils.LOG_ENTER(); + gateway.stop(); + ldap.stop(true); + TestUtils.LOG_EXIT(); + } + + public static void setupLdap() throws Exception { + String basedir = System.getProperty("basedir"); + if (basedir == null) { + basedir = new File(".").getCanonicalPath(); + } + + final Path path = FileSystems + .getDefault().getPath(basedir, "/src/test/resources/users.ldif"); + + ldapTransport = new TcpTransport(0); + ldap = new SimpleLdapDirectoryServer("dc=hadoop,dc=apache,dc=org", path.toFile(), ldapTransport); + ldap.start(); + LOG.info("LDAP port = " + ldapTransport.getPort()); + } + + public static void setupGateway() throws Exception { + + File targetDir = new File(System.getProperty("user.dir"), "target"); + File gatewayDir = new File(targetDir, "gateway-home-" + UUID.randomUUID()); + gatewayDir.mkdirs(); + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir(gatewayDir.getAbsolutePath()); + + File topoDir = new File(testConfig.getGatewayTopologyDir()); + topoDir.mkdirs(); + + File deployDir = new File(testConfig.getGatewayDeploymentDir()); + deployDir.mkdirs(); + + File descriptor = new File(topoDir, "test-cluster.xml"); + FileOutputStream stream = new FileOutputStream(descriptor); + createTopology().toStream(stream); + stream.close(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String, String> options = new HashMap<String, String>(); + options.put("persist-master", "false"); + options.put("master", "password"); + try { + srvcs.init(testConfig, options); + } catch (ServiceLifecycleException e) { + e.printStackTrace(); // I18N not required. + } + gateway = GatewayServer.startGateway(testConfig, srvcs); + MatcherAssert.assertThat("Failed to start gateway.", gateway, notNullValue()); + + LOG.info("Gateway port = " + gateway.getAddresses()[0].getPort()); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/test-cluster"; + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument(true) + .addRoot("topology") + .addTag("gateway") + .addTag("provider") + .addTag("role").addText("authentication") + .addTag("name").addText("ShiroProvider") + .addTag("enabled").addText("true") + .addTag("param") + .addTag("name").addText("main.ldapRealm") + .addTag("value").addText("org.apache.knox.gateway.shirorealm.KnoxLdapRealm").gotoParent() + .addTag("param") + .addTag("name").addText("main.ldapRealm.userDnTemplate") + .addTag("value").addText("uid={0},ou=people,dc=hadoop,dc=apache,dc=org").gotoParent() + .addTag("param") + .addTag("name").addText("main.ldapRealm.contextFactory.url") + .addTag("value").addText("ldap://localhost:" + ldapTransport.getAcceptor().getLocalAddress().getPort()).gotoParent() + .addTag("param") + .addTag("name").addText("main.ldapRealm.contextFactory.authenticationMechanism") + .addTag("value").addText("simple").gotoParent() + .addTag("param") + .addTag("name").addText("urls./**") + .addTag("value").addText("authcBasic").gotoParent().gotoParent() + .addTag("provider") + .addTag("role").addText("identity-assertion") + .addTag("enabled").addText("true") + .addTag("name").addText("Default").gotoParent() + .addTag("provider") + .gotoRoot() + .addTag("service") + .addTag("role").addText("HEALTH") + .gotoRoot(); + return xml; + } + - public static InputStream getResourceStream(String resource) throws IOException { - return getResourceUrl(resource).openStream(); - } - - public static URL getResourceUrl(String resource) { - URL url = ClassLoader.getSystemResource(getResourceName(resource)); - assertThat("Failed to find test resource " + resource, url, Matchers.notNullValue()); - return url; - } - - public static String getResourceName(String resource) { - return getResourceBaseName() + resource; - } - - public static String getResourceBaseName() { - return RESOURCE_BASE_CLASS.getName().replaceAll("\\.", "/") + "/"; - } - + @Test(timeout = TestUtils.MEDIUM_TIMEOUT) + public void testPingResource() { + TestUtils.LOG_ENTER(); + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/v1/ping"; + String body = given() + .auth().preemptive().basic(username, password) + .header("Accept", MediaType.TEXT_PLAIN) + .expect() + .statusCode(HttpStatus.SC_OK) + .contentType(MediaType.TEXT_PLAIN) + .when().get(serviceUrl).asString(); + Assert.assertEquals("OK", body.trim()); + TestUtils.LOG_EXIT(); + } + + @Test(timeout = TestUtils.MEDIUM_TIMEOUT) + public void testMetricsResource() { + TestUtils.LOG_ENTER(); + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/v1/metrics"; + String body = given() + .auth().preemptive().basic(username, password) + .expect() + .statusCode(HttpStatus.SC_OK) + .contentType(MediaType.APPLICATION_JSON) + .when().get(serviceUrl).asString(); + String version = JsonPath.from(body).getString("version"); + Map<String, String> hm = JsonPath.from(body).getMap(""); + Assert.assertTrue(hm.size() >= 6); + Assert.assertTrue(hm.keySet().containsAll(new HashSet<String>(Arrays.asList(new String[]{"timers", "histograms", + "counters", "gauges", "version", "meters"})))); + TestUtils.LOG_EXIT(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapDynamicGroupFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapDynamicGroupFuncTest.java index 2b0d28a,0000000..6886b74 mode 100755,000000..100755 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapDynamicGroupFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapDynamicGroupFuncTest.java @@@ -1,311 -1,0 +1,287 @@@ +/** + * 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.knox.gateway; + +import static com.jayway.restassured.RestAssured.given; +import static org.apache.hadoop.test.TestUtils.LOG_ENTER; +import static org.apache.hadoop.test.TestUtils.LOG_EXIT; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; - import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; - import java.io.InputStream; +import java.net.URL; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + - import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.knox.gateway.config.GatewayConfig; - import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.hadoop.test.TestUtils; +import org.apache.http.HttpStatus; +import org.apache.log4j.Appender; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; + +/** + * Functional test to verify : looking up ldap groups from directory + * and using them in acl authorization checks + * + */ +public class GatewayLdapDynamicGroupFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayLdapDynamicGroupFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger( GatewayLdapDynamicGroupFuncTest.class ); + + public static Enumeration<Appender> appenders; + public static GatewayConfig config; + public static GatewayServer gateway; + public static String gatewayUrl; + public static String clusterUrl; + public static String serviceUrl; + private static GatewayTestDriver driver = new GatewayTestDriver(); + + @BeforeClass + public static void setupSuite() throws Exception { + LOG_ENTER(); + //appenders = NoOpAppender.setUp(); + String basedir = System.getProperty("basedir"); + if (basedir == null) { + basedir = new File(".").getCanonicalPath(); + } + Path path = FileSystems.getDefault().getPath(basedir, "/src/test/resources/users-dynamic.ldif"); + driver.setupLdap( 0, path.toFile() ); + setupGateway(); + TestUtils.awaitNon404HttpStatus( new URL( serviceUrl ), 10000, 100 ); + LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + LOG_ENTER(); + gateway.stop(); + driver.cleanup(); + //FileUtils.deleteQuietly( new File( config.getGatewayHomeDir() ) ); + //NoOpAppender.tearDown( appenders ); + LOG_EXIT(); + } + + public static void setupGateway() throws IOException, Exception { + + File targetDir = new File( System.getProperty( "user.dir" ), "target" ); + File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); + gatewayDir.mkdirs(); + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); + + File topoDir = new File( testConfig.getGatewayTopologyDir() ); + topoDir.mkdirs(); + + File deployDir = new File( testConfig.getGatewayDeploymentDir() ); + deployDir.mkdirs(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String,String> options = new HashMap<>(); + options.put( "persist-master", "false" ); + options.put( "master", "password" ); + try { + srvcs.init( testConfig, options ); + } catch ( ServiceLifecycleException e ) { + e.printStackTrace(); // I18N not required. + } + + /* + System.setProperty(GatewayConfig.GATEWAY_HOME_VAR, gatewayDir.getAbsolutePath()); + System.err.println("GH 10: " + System.getProperty(GatewayConfig.GATEWAY_HOME_VAR)); + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + String[] argvals = {"create-alias", "ldcSystemPassword", "--value", "guest-password", "--master", "hadoop", "--cluster", "testdg-cluster"}; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + cli.run(argvals); + + outContent.reset(); + String[] args1 = {"list-alias", "--cluster", "testdg-cluster", "--master", "hadoop"}; + cli = new KnoxCLI(); + cli.run(args1); + System.err.println("ALIAS LIST: " + outContent.toString()); + + AliasService as1 = cli.getGatewayServices().getService(GatewayServices.ALIAS_SERVICE); + char[] passwordChars1 = as1.getPasswordFromAliasForCluster( "test-cluster", "ldcsystemPassword"); + System.err.println("ALIAS value1: " + new String(passwordChars1)); + */ + + gateway = GatewayServer.startGateway( testConfig, srvcs ); + MatcherAssert.assertThat( "Failed to start gateway.", gateway, notNullValue() ); + + LOG.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/testdg-cluster"; + serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + + ///* + GatewayServices services = GatewayServer.getGatewayServices(); + AliasService aliasService = (AliasService)services.getService(GatewayServices.ALIAS_SERVICE); + aliasService.addAliasForCluster("testdg-cluster", "ldcSystemPassword", "guest-password"); + + char[] password1 = aliasService.getPasswordFromAliasForCluster( "testdg-cluster", "ldcSystemPassword"); + //System.err.println("SETUP password 10: " + ((password1 == null) ? "NULL" : new String(password1))); + + File descriptor = new File( topoDir, "testdg-cluster.xml" ); + FileOutputStream stream = new FileOutputStream( descriptor ); + createTopology().toStream( stream ); + stream.close(); + + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapGroupContextFactory" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory" ) + .addTag( "value" ).addText( "$ldapGroupContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( driver.getLdapUrl()) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.authorizationEnabled" ) + .addTag( "value" ).addText( "true" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemAuthenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.searchBase" ) + .addTag( "value" ).addText( "ou=groups,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.groupObjectClass" ) + .addTag( "value" ).addText( "groupofurls" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttribute" ) + .addTag( "value" ).addText( "memberurl" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttributeValueTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemUsername" ) + .addTag( "value" ).addText( "uid=guest,ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.clusterName" ) + .addTag( "value" ).addText( "testdg-cluster" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemPassword" ) + .addTag( "value" ).addText( "S{ALIAS=ldcSystemPassword}" ) + // .addTag( "value" ).addText( "guest-password" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "authorization" ) + .addTag( "name" ).addText( "AclsAuthz" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "test-service-role.acl" ) // FIXME[dilli] + .addTag( "value" ).addText( "*;directors;*" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + - public static InputStream getResourceStream( String resource ) throws IOException { - return getResourceUrl( resource ).openStream(); - } - - public static URL getResourceUrl( String resource ) { - URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); - assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); - return url; - } - - public static String getResourceName( String resource ) { - return getResourceBaseName() + resource; - } - - public static String getResourceBaseName() { - return RESOURCE_BASE_CLASS.getName().replaceAll( "\\.", "/" ) + "/"; - } - + // @Test + public void waitForManualTesting() throws IOException { + System.in.read(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testGroupMember() throws ClassNotFoundException, Exception { + LOG_ENTER(); + String username = "bob"; + String password = "bob-password"; + String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_OK ) + .contentType( "text/plain" ) + .body( is( "test-service-response" ) ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testNonGroupMember() throws ClassNotFoundException { + LOG_ENTER(); + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_FORBIDDEN ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapGroupFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapGroupFuncTest.java index cb166b3,0000000..435399a mode 100644,000000..100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapGroupFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapGroupFuncTest.java @@@ -1,308 -1,0 +1,283 @@@ +/** + * 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.knox.gateway; + +import static com.jayway.restassured.RestAssured.given; +import static org.apache.hadoop.test.TestUtils.LOG_ENTER; +import static org.apache.hadoop.test.TestUtils.LOG_EXIT; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; - import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; - import java.net.InetSocketAddress; +import java.net.URL; - import java.nio.file.FileSystems; - import java.nio.file.Path; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + - import org.apache.directory.server.protocol.shared.transport.TcpTransport; ++ +import org.apache.knox.gateway.config.GatewayConfig; - import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.hadoop.test.TestUtils; +import org.apache.http.HttpStatus; +import org.apache.log4j.Appender; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; + +/** + * Functional test to verify : looking up ldap groups from directory + * and using them in acl authorization checks + * + */ +public class GatewayLdapGroupFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayLdapGroupFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger( GatewayLdapGroupFuncTest.class ); + + public static Enumeration<Appender> appenders; + public static GatewayConfig config; + public static GatewayServer gateway; + public static String gatewayUrl; + public static String clusterUrl; + public static String serviceUrl; + private static GatewayTestDriver driver = new GatewayTestDriver(); + + @BeforeClass + public static void setupSuite() throws Exception { + LOG_ENTER(); + //appenders = NoOpAppender.setUp(); + driver.setupLdap(0); + setupGateway(); + TestUtils.awaitNon404HttpStatus( new URL( serviceUrl ), 10000, 100 ); + LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + LOG_ENTER(); + gateway.stop(); + driver.cleanup(); + //FileUtils.deleteQuietly( new File( config.getGatewayHomeDir() ) ); + //NoOpAppender.tearDown( appenders ); + LOG_EXIT(); + } + + public static void setupGateway() throws Exception { + + File targetDir = new File( System.getProperty( "user.dir" ), "target" ); + File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); + gatewayDir.mkdirs(); + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); + + File topoDir = new File( testConfig.getGatewayTopologyDir() ); + topoDir.mkdirs(); + + File deployDir = new File( testConfig.getGatewayDeploymentDir() ); + deployDir.mkdirs(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String,String> options = new HashMap<>(); + options.put( "persist-master", "true" ); + options.put( "master", "hadoop" ); + + try { + srvcs.init( testConfig, options ); + } catch ( ServiceLifecycleException e ) { + e.printStackTrace(); // I18N not required. + } + + /* + System.setProperty(GatewayConfig.GATEWAY_HOME_VAR, gatewayDir.getAbsolutePath()); + System.err.println("GH 10: " + System.getProperty(GatewayConfig.GATEWAY_HOME_VAR)); + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + String[] argvals = {"create-alias", "ldcSystemPassword", "--value", "guest-password", "--master", "hadoop", "--cluster", "test-cluster"}; + KnoxCLI cli = new KnoxCLI(); + cli.setConf(new GatewayConfigImpl()); + cli.run(argvals); + + outContent.reset(); + String[] args1 = {"list-alias", "--cluster", "test-cluster", "--master", "hadoop"}; + cli = new KnoxCLI(); + cli.run(args1); + System.err.println("ALIAS LIST: " + outContent.toString()); + + AliasService as1 = cli.getGatewayServices().getService(GatewayServices.ALIAS_SERVICE); + char[] passwordChars1 = as1.getPasswordFromAliasForCluster( "test-cluster", "ldcsystemPassword"); + System.err.println("ALIAS value1: " + new String(passwordChars1)); + */ + + gateway = GatewayServer.startGateway( testConfig, srvcs ); + MatcherAssert.assertThat( "Failed to start gateway.", gateway, notNullValue() ); + + LOG.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/test-cluster"; + serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + + ///* + GatewayServices services = GatewayServer.getGatewayServices(); + AliasService aliasService = (AliasService)services.getService(GatewayServices.ALIAS_SERVICE); + aliasService.addAliasForCluster("test-cluster", "ldcSystemPassword", "guest-password"); + + char[] password1 = aliasService.getPasswordFromAliasForCluster( "test-cluster", "ldcSystemPassword"); + //System.err.println("SETUP password 10: " + ((password1 == null) ? "NULL" : new String(password1))); + + File descriptor = new File( topoDir, "test-cluster.xml" ); + FileOutputStream stream = new FileOutputStream( descriptor ); + createTopology().toStream( stream ); + stream.close(); + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapGroupContextFactory" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory" ) + .addTag( "value" ).addText( "$ldapGroupContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( driver.getLdapUrl()) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.authorizationEnabled" ) + .addTag( "value" ).addText( "true" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemAuthenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.searchBase" ) + .addTag( "value" ).addText( "ou=groups,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.groupObjectClass" ) + .addTag( "value" ).addText( "groupofnames" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttribute" ) + .addTag( "value" ).addText( "member" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttributeValueTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.clusterName" ) + .addTag( "value" ).addText( "test-cluster" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemUsername" ) + .addTag( "value" ).addText( "uid=guest,ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemPassword" ) + .addTag( "value" ).addText( "S{ALIAS=ldcSystemPassword}" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "authorization" ) + .addTag( "name" ).addText( "AclsAuthz" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "test-service-role.acl" ) // FIXME[dilli] + .addTag( "value" ).addText( "*;analyst;*" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + - public static InputStream getResourceStream( String resource ) throws IOException { - return getResourceUrl( resource ).openStream(); - } - - public static URL getResourceUrl( String resource ) { - URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); - assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); - return url; - } - - public static String getResourceName( String resource ) { - return getResourceBaseName() + resource; - } - - public static String getResourceBaseName() { - return RESOURCE_BASE_CLASS.getName().replaceAll( "\\.", "/" ) + "/"; - } - + @Ignore + // @Test + public void waitForManualTesting() throws IOException { + System.in.read(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testGroupMember() throws ClassNotFoundException, Exception { + LOG_ENTER(); + String username = "sam"; + String password = "sam-password"; + String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_OK ) + .contentType( "text/plain" ) + .body( is( "test-service-response" ) ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testNonGroupMember() throws ClassNotFoundException { + LOG_ENTER(); + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_FORBIDDEN ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapPosixGroupFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapPosixGroupFuncTest.java index 64d1ba7,0000000..4ad76fb mode 100644,000000..100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapPosixGroupFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapPosixGroupFuncTest.java @@@ -1,287 -1,0 +1,273 @@@ +/** + * 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.knox.gateway; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; +import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.knox.gateway.services.security.AliasService; +import org.apache.hadoop.test.TestUtils; +import org.apache.hadoop.test.category.ReleaseTest; +import org.apache.http.HttpStatus; +import org.apache.log4j.Appender; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; - import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.jayway.restassured.RestAssured.given; +import static org.apache.hadoop.test.TestUtils.LOG_ENTER; +import static org.apache.hadoop.test.TestUtils.LOG_EXIT; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; - import static org.junit.Assert.assertThat; - import static org.junit.Assert.fail; + +/** + * Functional test to verify : looking up ldap groups from directory + * and using them in acl authorization checks + * + */ +@Category(ReleaseTest.class) +public class GatewayLdapPosixGroupFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayLdapPosixGroupFuncTest.class; ++ private static final Class<?> RESOURCE_BASE_CLASS = GatewayLdapPosixGroupFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger( GatewayLdapPosixGroupFuncTest.class ); + + public static Enumeration<Appender> appenders; + public static GatewayConfig config; + public static GatewayServer gateway; + public static String gatewayUrl; + public static String clusterUrl; + public static String serviceUrl; + private static GatewayTestDriver driver = new GatewayTestDriver(); + + @BeforeClass + public static void setupSuite() throws Exception { + LOG_ENTER(); + //appenders = NoOpAppender.setUp(); - URL usersUrl = getResourceUrl( "users.ldif" ); ++ URL usersUrl = TestUtils.getResourceUrl( GatewayLdapPosixGroupFuncTest.class, "users.ldif" ); + driver.setupLdap( 0, new File( usersUrl.toURI() ) ); + setupGateway(); + TestUtils.awaitNon404HttpStatus( new URL( serviceUrl ), 10000, 100 ); + LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + LOG_ENTER(); + gateway.stop(); + driver.cleanup(); + //FileUtils.deleteQuietly( new File( config.getGatewayHomeDir() ) ); + //NoOpAppender.tearDown( appenders ); + LOG_EXIT(); + } + + public static void setupGateway() throws Exception { + + File targetDir = new File( System.getProperty( "user.dir" ), "target" ); + File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); + gatewayDir.mkdirs(); + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); + + File topoDir = new File( testConfig.getGatewayTopologyDir() ); + topoDir.mkdirs(); + + File deployDir = new File( testConfig.getGatewayDeploymentDir() ); + deployDir.mkdirs(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String,String> options = new HashMap<>(); + options.put( "persist-master", "true" ); + options.put( "master", "hadoop" ); + + try { + srvcs.init( testConfig, options ); + } catch ( ServiceLifecycleException e ) { + e.printStackTrace(); // I18N not required. + } + + gateway = GatewayServer.startGateway( testConfig, srvcs ); + MatcherAssert.assertThat( "Failed to start gateway.", gateway, notNullValue() ); + + LOG.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/test-cluster"; + serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; + + GatewayServices services = GatewayServer.getGatewayServices(); + AliasService aliasService = (AliasService)services.getService(GatewayServices.ALIAS_SERVICE); + aliasService.addAliasForCluster("test-cluster", "ldcSystemPassword", "guest-password"); + + char[] password1 = aliasService.getPasswordFromAliasForCluster( "test-cluster", "ldcSystemPassword"); + + File descriptor = new File( topoDir, "test-cluster.xml" ); + OutputStream stream = new FileOutputStream( descriptor ); + createTopology().toStream( stream ); + stream.close(); + + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapGroupContextFactory" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory" ) + .addTag( "value" ).addText( "$ldapGroupContextFactory" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( driver.getLdapUrl() ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.authorizationEnabled" ) + .addTag( "value" ).addText( "true" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemAuthenticationMechanism" ) + .addTag( "value" ).addText( "simple" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.searchBase" ) + .addTag( "value" ).addText( "ou=groups,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.groupObjectClass" ) + .addTag( "value" ).addText( "posixGroup" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttribute" ) + .addTag( "value" ).addText( "memberUid" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.memberAttributeValueTemplate" ) + .addTag( "value" ).addText( "uid={0}" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.clusterName" ) + .addTag( "value" ).addText( "test-cluster" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemUsername" ) + .addTag( "value" ).addText( "uid=guest,ou=people,dc=hadoop,dc=apache,dc=org" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.systemPassword" ) + .addTag( "value" ).addText( "S{ALIAS=ldcSystemPassword}" ) + .gotoParent().addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "authorization" ) + .addTag( "name" ).addText( "AclsAuthz" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "test-service-role.acl" ) + .addTag( "value" ).addText( "*;analyst;*" ) + + .gotoParent().gotoParent().addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-service-role" ) + .gotoRoot(); + + return xml; + } + - public static InputStream getResourceStream( String resource ) throws IOException { - return getResourceUrl( resource ).openStream(); - } - - public static URL getResourceUrl( String resource ) { - URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); - assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); - return url; - } - - public static String getResourceName( String resource ) { ++ private static String getResourceName( String resource ) { + return getResourceBaseName() + resource; + } + - public static String getResourceBaseName() { ++ private static String getResourceBaseName() { + return RESOURCE_BASE_CLASS.getName().replaceAll( "\\.", "/" ) + "/"; + } + + @Ignore + // @Test + public void waitForManualTesting() throws IOException { + System.in.read(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testGroupMember() throws ClassNotFoundException, Exception { + LOG_ENTER(); + String username = "sam"; + String password = "sam-password"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_OK ) + .contentType( "text/plain" ) + .body( is( "test-service-response" ) ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testNonGroupMember() throws ClassNotFoundException { + LOG_ENTER(); + String username = "guest"; + String password = "guest-password"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_FORBIDDEN ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLocalServiceFuncTest.java ---------------------------------------------------------------------- diff --cc gateway-test/src/test/java/org/apache/knox/gateway/GatewayLocalServiceFuncTest.java index 116793c,0000000..6fca9cc mode 100644,000000..100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLocalServiceFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayLocalServiceFuncTest.java @@@ -1,208 -1,0 +1,185 @@@ +/** + * 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.knox.gateway; + +import com.mycila.xmltool.XMLDoc; +import com.mycila.xmltool.XMLTag; +import org.apache.commons.io.FileUtils; +import org.apache.directory.server.protocol.shared.transport.TcpTransport; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.security.ldap.SimpleLdapDirectoryServer; +import org.apache.knox.gateway.services.DefaultGatewayServices; +import org.apache.knox.gateway.services.ServiceLifecycleException; +import org.apache.hadoop.test.TestUtils; +import org.apache.hadoop.test.log.NoOpAppender; +import org.apache.http.HttpStatus; +import org.apache.log4j.Appender; +import org.hamcrest.MatcherAssert; - import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; - import java.io.IOException; - import java.io.InputStream; - import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.jayway.restassured.RestAssured.given; +import static org.apache.hadoop.test.TestUtils.LOG_ENTER; +import static org.apache.hadoop.test.TestUtils.LOG_EXIT; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +public class GatewayLocalServiceFuncTest { + - private static Class RESOURCE_BASE_CLASS = GatewayLocalServiceFuncTest.class; + private static Logger LOG = LoggerFactory.getLogger( GatewayTestDriver.class ); + + public static Enumeration<Appender> appenders; + public static GatewayConfig config; + public static GatewayServer gateway; + public static String gatewayUrl; + public static String clusterUrl; + private static GatewayTestDriver driver = new GatewayTestDriver(); + + @BeforeClass + public static void setupSuite() throws Exception { + LOG_ENTER(); + appenders = NoOpAppender.setUp(); + driver.setupLdap(0); + setupGateway(); + LOG_EXIT(); + } + + @AfterClass + public static void cleanupSuite() throws Exception { + LOG_ENTER(); + gateway.stop(); + driver.cleanup(); + FileUtils.deleteQuietly( new File( config.getGatewayConfDir() ) ); + FileUtils.deleteQuietly( new File( config.getGatewayDataDir() ) ); + NoOpAppender.tearDown( appenders ); + LOG_EXIT(); + } + + public static void setupGateway() throws Exception { + + File targetDir = new File( System.getProperty( "user.dir" ), "target" ); + File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); + gatewayDir.mkdirs(); + + GatewayTestConfig testConfig = new GatewayTestConfig(); + config = testConfig; + testConfig.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); + + File topoDir = new File( testConfig.getGatewayTopologyDir() ); + topoDir.mkdirs(); + + File deployDir = new File( testConfig.getGatewayDeploymentDir() ); + deployDir.mkdirs(); + + File descriptor = new File( topoDir, "cluster.xml" ); + FileOutputStream stream = new FileOutputStream( descriptor ); + createTopology().toStream( stream ); + stream.close(); + + DefaultGatewayServices srvcs = new DefaultGatewayServices(); + Map<String,String> options = new HashMap<>(); + options.put( "persist-master", "false" ); + options.put( "master", "password" ); + try { + srvcs.init( testConfig, options ); + } catch ( ServiceLifecycleException e ) { + e.printStackTrace(); // I18N not required. + } + gateway = GatewayServer.startGateway( testConfig, srvcs ); + MatcherAssert.assertThat( "Failed to start gateway.", gateway, notNullValue() ); + + LOG.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); + + gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); + clusterUrl = gatewayUrl + "/cluster"; + } + + private static XMLTag createTopology() { + XMLTag xml = XMLDoc.newDocument( true ) + .addRoot( "topology" ) + .addTag( "gateway" ) + .addTag( "provider" ) + .addTag( "role" ).addText( "authentication" ) + .addTag( "name" ).addText( "ShiroProvider" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm" ) + .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" ) + .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" ) + .addTag( "value" ).addText( driver.getLdapUrl() ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" ) + .addTag( "value" ).addText( "simple" ).gotoParent() + .addTag( "param" ) + .addTag( "name" ).addText( "urls./**" ) + .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent() + .addTag( "provider" ) + .addTag( "role" ).addText( "identity-assertion" ) + .addTag( "enabled" ).addText( "true" ) + .addTag( "name" ).addText( "Default" ).gotoParent() + .addTag( "provider" ) + .gotoRoot() + .addTag( "service" ) + .addTag( "role" ).addText( "test-jersey-service-role" ) + .gotoRoot(); + // System.out.println( "GATEWAY=" + xml.toString() ); + return xml; + } + + @Test( timeout = TestUtils.MEDIUM_TIMEOUT ) + public void testJerseyService() throws ClassNotFoundException { + LOG_ENTER(); + assertThat( ClassLoader.getSystemClassLoader().loadClass( "org.glassfish.jersey.servlet.ServletContainer" ), notNullValue() ); + assertThat( ClassLoader.getSystemClassLoader().loadClass( + "org.apache.knox.gateway.jersey.JerseyDispatchDeploymentContributor"), notNullValue() ); + assertThat( ClassLoader.getSystemClassLoader().loadClass( + "org.apache.knox.gateway.jersey.JerseyServiceDeploymentContributorBase"), notNullValue() ); + assertThat( ClassLoader.getSystemClassLoader().loadClass( + "org.apache.knox.gateway.TestJerseyService"), notNullValue() ); + + String username = "guest"; + String password = "guest-password"; + String serviceUrl = clusterUrl + "/test-jersey-service/test-jersey-resource-path"; + given() + //.log().all() + .auth().preemptive().basic( username, password ) + .expect() + //.log().all() + .statusCode( HttpStatus.SC_OK ) + .contentType( "text/plain" ) + .body( is( "test-jersey-resource-response" ) ) + .when().get( serviceUrl ); + LOG_EXIT(); + } + - public static InputStream getResourceStream( String resource ) throws IOException { - return getResourceUrl( resource ).openStream(); - } - - public static URL getResourceUrl( String resource ) { - URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); - assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); - return url; - } - - public static String getResourceName( String resource ) { - return getResourceBaseName() + resource; - } - - public static String getResourceBaseName() { - return RESOURCE_BASE_CLASS.getName().replaceAll( "\\.", "/" ) + "/"; - } - +}