securing the metadata client
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/43868812 Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/43868812 Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/43868812 Branch: refs/remotes/origin/master Commit: 438688121370628ea0879bae748048867e44c05c Parents: bb3022b Author: Jon Maron <[email protected]> Authored: Fri May 8 18:07:13 2015 -0400 Committer: Jon Maron <[email protected]> Committed: Fri May 8 18:07:13 2015 -0400 ---------------------------------------------------------------------- addons/hive-bridge/pom.xml | 34 ++- .../hive/hook/BaseSSLAndKerberosTest.java | 141 ++++++++++ .../hook/NegativeSSLAndKerberosHiveHookIT.java | 159 ++++++++++++ .../hive/hook/SSLAndKerberosHiveHookIT.java | 257 +++++++++++++++++++ .../metadata/hive/hook/SSLHiveHookIT.java | 253 ++++++++++++++++++ client/pom.xml | 65 +++++ .../hadoop/metadata/MetadataServiceClient.java | 31 ++- .../apache/hadoop/metadata/PropertiesUtil.java | 60 +++++ .../metadata/security/SecureClientUtils.java | 195 ++++++++++++++ .../metadata/security/SecurityProperties.java | 35 +++ .../metadata/security/BaseSecurityTest.java | 128 +++++++++ pom.xml | 4 +- repository/pom.xml | 5 + .../apache/hadoop/metadata/PropertiesUtil.java | 50 ---- webapp/pom.xml | 9 + .../util/CredentialProviderUtility.java | 6 +- .../filters/MetadataAuthenticationFilter.java | 7 +- .../web/listeners/GuiceServletConfig.java | 12 +- .../web/service/SecureEmbeddedServer.java | 13 +- .../metadata/CredentialProviderUtilityIT.java | 26 +- .../hadoop/metadata/web/BaseSecurityTest.java | 128 --------- .../MetadataAuthenticationKerberosFilterIT.java | 11 +- .../MetadataAuthenticationSimpleFilterIT.java | 9 +- .../web/listeners/LoginProcessorIT.java | 13 +- .../web/service/SecureEmbeddedServerIT.java | 4 +- .../web/service/SecureEmbeddedServerITBase.java | 14 +- 26 files changed, 1431 insertions(+), 238 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/addons/hive-bridge/pom.xml ---------------------------------------------------------------------- diff --git a/addons/hive-bridge/pom.xml b/addons/hive-bridge/pom.xml index 03d2dcf..fa3df78 100755 --- a/addons/hive-bridge/pom.xml +++ b/addons/hive-bridge/pom.xml @@ -35,19 +35,22 @@ <properties> <hive.version>1.1.0</hive.version> <calcite.version>0.9.2-incubating</calcite.version> - <hadoop.version>2.5.0</hadoop.version> + <hadoop.version>2.6.0</hadoop.version> </properties> <dependencies> <dependency> <groupId>org.apache.hadoop.metadata</groupId> <artifactId>metadata-client</artifactId> + <version>${version}</version> <exclusions> <exclusion> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclusion> </exclusions> + <scope>runtime</scope> + <type>test-jar</type> </dependency> <dependency> @@ -55,6 +58,13 @@ <artifactId>metadata-typesystem</artifactId> </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-minikdc</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> @@ -92,7 +102,12 @@ <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> - <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-annotations</artifactId> + <version>${hadoop.version}</version> </dependency> <dependency> @@ -104,9 +119,14 @@ <groupId>org.apache.hadoop.metadata</groupId> <artifactId>metadata-webapp</artifactId> <version>${project.version}</version> - <type>war</type> - <scope>test</scope> + <classifier>classes</classifier> </dependency> + + <dependency> + <groupId>org.mortbay.jetty</groupId> + <artifactId>jetty</artifactId> + </dependency> + </dependencies> <build> @@ -254,6 +274,12 @@ <skip>false</skip> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <inherited>true</inherited> + <extensions>true</extensions> + </plugin> </plugins> </build> </project> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/BaseSSLAndKerberosTest.java ---------------------------------------------------------------------- diff --git a/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/BaseSSLAndKerberosTest.java b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/BaseSSLAndKerberosTest.java new file mode 100644 index 0000000..75c23bc --- /dev/null +++ b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/BaseSSLAndKerberosTest.java @@ -0,0 +1,141 @@ +/* + * 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.hadoop.metadata.hive.hook; + +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.metadata.hive.bridge.HiveMetaStoreBridge; +import org.apache.hadoop.metadata.security.BaseSecurityTest; +import org.apache.hadoop.metadata.web.service.SecureEmbeddedServer; +import org.apache.hadoop.security.alias.CredentialProvider; +import org.apache.hadoop.security.alias.CredentialProviderFactory; +import org.mortbay.jetty.Server; + +import java.io.File; +import java.io.IOException; + +import static org.apache.hadoop.metadata.security.SecurityProperties.KEYSTORE_PASSWORD_KEY; +import static org.apache.hadoop.metadata.security.SecurityProperties.SERVER_CERT_PASSWORD_KEY; +import static org.apache.hadoop.metadata.security.SecurityProperties.TRUSTSTORE_PASSWORD_KEY; + +/** + * + */ +public class BaseSSLAndKerberosTest extends BaseSecurityTest { + public static final String TESTUSER = "testuser"; + public static final String TESTPASS = "testpass"; + protected static final String DGI_URL = "https://localhost:21443/"; + protected Path jksPath; + protected String providerUrl; + protected File httpKeytabFile; + private File userKeytabFile; + + class TestSecureEmbeddedServer extends SecureEmbeddedServer { + + public TestSecureEmbeddedServer(int port, String path) throws IOException { + super(port, path); + } + + public Server getServer() { + return server; + } + + @Override + public PropertiesConfiguration getConfiguration() { + return super.getConfiguration(); + } + } + + protected void setupCredentials() throws Exception { + Configuration conf = new Configuration(false); + + File file = new File(jksPath.toUri().getPath()); + file.delete(); + conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, providerUrl); + + CredentialProvider provider = + CredentialProviderFactory.getProviders(conf).get(0); + + // create new aliases + try { + + char[] storepass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + KEYSTORE_PASSWORD_KEY, storepass); + + char[] trustpass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + TRUSTSTORE_PASSWORD_KEY, trustpass); + + char[] trustpass2 = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + "ssl.client.truststore.password", trustpass2); + + char[] certpass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + SERVER_CERT_PASSWORD_KEY, certpass); + + // write out so that it can be found in checks + provider.flush(); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + public void setupKDCAndPrincipals() throws Exception { + // set up the KDC + File kdcWorkDir = startKDC(); + + userKeytabFile = createKeytab(kdc, kdcWorkDir, "dgi", "dgi.keytab"); + httpKeytabFile = createKeytab(kdc, kdcWorkDir, "HTTP", "spnego.service.keytab"); + + // create a test user principal + kdc.createPrincipal(TESTUSER, TESTPASS); + + StringBuilder jaas = new StringBuilder(1024); + jaas.append("TestUser {\n" + + " com.sun.security.auth.module.Krb5LoginModule required\nuseTicketCache=true;\n" + + "};\n"); + jaas.append(createJAASEntry("Client", "dgi", userKeytabFile)); + jaas.append(createJAASEntry("Server", "HTTP", httpKeytabFile)); + + File jaasFile = new File(kdcWorkDir, "jaas.txt"); + FileUtils.write(jaasFile, jaas.toString()); + bindJVMtoJAASFile(jaasFile); + } + + protected String getWarPath() { + return String.format("/../../webapp/target/metadata-webapp-%s", + System.getProperty("project.version", "0.1-incubating-SNAPSHOT")); + } + + protected HiveConf getHiveConf() { + HiveConf hiveConf = new HiveConf(this.getClass()); + hiveConf.setVar(HiveConf.ConfVars.PREEXECHOOKS, ""); + hiveConf.setVar(HiveConf.ConfVars.POSTEXECHOOKS, HiveHook.class.getName()); + hiveConf.setBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY, false); + hiveConf.setVar(HiveConf.ConfVars.METASTOREWAREHOUSE, System.getProperty("user.dir") + "/target/metastore"); + hiveConf.set(HiveMetaStoreBridge.DGI_URL_PROPERTY, DGI_URL); + hiveConf.set("javax.jdo.option.ConnectionURL", "jdbc:derby:./target/metastore_db;create=true"); + hiveConf.set("hive.hook.dgi.synchronous", "true"); + return hiveConf; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/NegativeSSLAndKerberosHiveHookIT.java ---------------------------------------------------------------------- diff --git a/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/NegativeSSLAndKerberosHiveHookIT.java b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/NegativeSSLAndKerberosHiveHookIT.java new file mode 100755 index 0000000..af073f5 --- /dev/null +++ b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/NegativeSSLAndKerberosHiveHookIT.java @@ -0,0 +1,159 @@ +/** + * 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.hadoop.metadata.hive.hook; + +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.metadata.PropertiesUtil; +import org.apache.hadoop.metadata.security.SecurityProperties; +import org.apache.hadoop.security.alias.JavaKeyStoreProvider; +import org.apache.hadoop.security.ssl.SSLFactory; +import org.apache.hadoop.security.ssl.SSLHostnameVerifier; +import org.mortbay.jetty.webapp.WebAppContext; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileWriter; +import java.net.URL; +import java.nio.file.Files; + +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + +/** + * Perform all the necessary setup steps for client and server comm over SSL/Kerberos, but then don't estalish a + * kerberos user for the invocation. Need a separate use case since the Jersey layer cached the URL connection handler, + * which indirectly caches the kerberos delegation token. + */ +public class NegativeSSLAndKerberosHiveHookIT extends BaseSSLAndKerberosTest { + + private Driver driver; + private SessionState ss; + private TestSecureEmbeddedServer secureEmbeddedServer; + private String originalConf; + + @BeforeClass + public void setUp() throws Exception { + //Set-up hive session + HiveConf conf = getHiveConf(); + driver = new Driver(conf); + ss = new SessionState(conf, System.getProperty("user.name")); + ss = SessionState.start(ss); + SessionState.setCurrentSessionState(ss); + + jksPath = new Path(Files.createTempDirectory("tempproviders").toString(), "test.jks"); + providerUrl = JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri(); + + String persistDir = null; + URL resource = NegativeSSLAndKerberosHiveHookIT.class.getResource("/"); + if (resource != null) { + persistDir = resource.toURI().getPath(); + } + // delete prior ssl-client.xml file + resource = NegativeSSLAndKerberosHiveHookIT.class.getResource("/" + SecurityProperties.SSL_CLIENT_PROPERTIES); + if (resource != null) { + File sslClientFile = new File(persistDir, SecurityProperties.SSL_CLIENT_PROPERTIES); + if (sslClientFile != null && sslClientFile.exists()) { + sslClientFile.delete(); + } + } + setupKDCAndPrincipals(); + setupCredentials(); + + // client will actually only leverage subset of these properties + final PropertiesConfiguration configuration = new PropertiesConfiguration(); + configuration.setProperty(TLS_ENABLED, true); + configuration.setProperty(TRUSTSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(KEYSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(CERT_STORES_CREDENTIAL_PROVIDER_PATH, providerUrl); + configuration.setProperty("metadata.http.authentication.type", "kerberos"); + configuration.setProperty(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, SSLHostnameVerifier.DEFAULT_AND_LOCALHOST.toString()); + + configuration.save(new FileWriter(persistDir + File.separator + "client.properties")); + + String confLocation = System.getProperty("metadata.conf"); + URL url; + if (confLocation == null) { + url = PropertiesUtil.class.getResource("/application.properties"); + } else { + url = new File(confLocation, "application.properties").toURI().toURL(); + } + configuration.load(url); + configuration.setProperty(TLS_ENABLED, true); + configuration.setProperty("metadata.http.authentication.enabled", "true"); + configuration.setProperty("metadata.http.authentication.kerberos.principal", "HTTP/localhost@" + kdc.getRealm()); + configuration.setProperty("metadata.http.authentication.kerberos.keytab", httpKeytabFile.getAbsolutePath()); + configuration.setProperty("metadata.http.authentication.kerberos.name.rules", + "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\nDEFAULT"); + + configuration.save(new FileWriter(persistDir + File.separator + "application.properties")); + + secureEmbeddedServer = new TestSecureEmbeddedServer(21443, "webapp/target/metadata-governance") { + @Override + public PropertiesConfiguration getConfiguration() { + return configuration; + } + }; + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(System.getProperty("user.dir") + getWarPath()); + secureEmbeddedServer.getServer().setHandler(webapp); + + // save original setting + originalConf = System.getProperty("metadata.conf"); + System.setProperty("metadata.conf", persistDir); + secureEmbeddedServer.getServer().start(); + + } + + @AfterClass + public void tearDown() throws Exception { + if (secureEmbeddedServer != null) { + secureEmbeddedServer.getServer().stop(); + } + + if (kdc != null) { + kdc.stop(); + } + + if (originalConf != null) { + System.setProperty("metadata.conf", originalConf); + } + } + + private void runCommand(final String cmd) throws Exception { + ss.setCommandType(null); + driver.run(cmd); + Assert.assertNotNull(driver.getErrorMsg()); + Assert.assertTrue(driver.getErrorMsg().contains("Mechanism level: Failed to find any Kerberos tgt")); + } + + @Test + public void testUnsecuredCreateDatabase() throws Exception { + String dbName = "db" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create database " + dbName); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLAndKerberosHiveHookIT.java ---------------------------------------------------------------------- diff --git a/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLAndKerberosHiveHookIT.java b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLAndKerberosHiveHookIT.java new file mode 100755 index 0000000..0b28e65 --- /dev/null +++ b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLAndKerberosHiveHookIT.java @@ -0,0 +1,257 @@ +/** + * 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.hadoop.metadata.hive.hook; + +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.metadata.MetadataException; +import org.apache.hadoop.metadata.MetadataServiceClient; +import org.apache.hadoop.metadata.PropertiesUtil; +import org.apache.hadoop.metadata.hive.model.HiveDataTypes; +import org.apache.hadoop.metadata.security.SecurityProperties; +import org.apache.hadoop.security.alias.JavaKeyStoreProvider; +import org.apache.hadoop.security.ssl.SSLFactory; +import org.apache.hadoop.security.ssl.SSLHostnameVerifier; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.mortbay.jetty.webapp.WebAppContext; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import javax.security.auth.Subject; +import javax.security.auth.callback.*; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.security.PrivilegedExceptionAction; + +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + +public class SSLAndKerberosHiveHookIT extends BaseSSLAndKerberosTest { + public static final String TEST_USER_JAAS_SECTION = "TestUser"; + public static final String TESTUSER = "testuser"; + public static final String TESTPASS = "testpass"; + + private static final String DGI_URL = "https://localhost:21443/"; + private Driver driver; + private MetadataServiceClient dgiCLient; + private SessionState ss; + private TestSecureEmbeddedServer secureEmbeddedServer; + private Subject subject; + private String originalConf; + + @BeforeClass + public void setUp() throws Exception { + //Set-up hive session + HiveConf conf = getHiveConf(); + driver = new Driver(conf); + ss = new SessionState(conf, System.getProperty("user.name")); + ss = SessionState.start(ss); + SessionState.setCurrentSessionState(ss); + + jksPath = new Path(Files.createTempDirectory("tempproviders").toString(), "test.jks"); + providerUrl = JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri(); + + String persistDir = null; + URL resource = SSLAndKerberosHiveHookIT.class.getResource("/"); + if (resource != null) { + persistDir = resource.toURI().getPath(); + } + // delete prior ssl-client.xml file + resource = SSLAndKerberosHiveHookIT.class.getResource("/" + SecurityProperties.SSL_CLIENT_PROPERTIES); + if (resource != null) { + File sslClientFile = new File(persistDir, SecurityProperties.SSL_CLIENT_PROPERTIES); + if (sslClientFile != null && sslClientFile.exists()) { + sslClientFile.delete(); + } + } + setupKDCAndPrincipals(); + setupCredentials(); + + // client will actually only leverage subset of these properties + final PropertiesConfiguration configuration = new PropertiesConfiguration(); + configuration.setProperty(TLS_ENABLED, true); + configuration.setProperty(TRUSTSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(KEYSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(CERT_STORES_CREDENTIAL_PROVIDER_PATH, providerUrl); + configuration.setProperty("metadata.http.authentication.type", "kerberos"); + configuration.setProperty(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, SSLHostnameVerifier.DEFAULT_AND_LOCALHOST.toString()); + + configuration.save(new FileWriter(persistDir + File.separator + "client.properties")); + + String confLocation = System.getProperty("metadata.conf"); + URL url; + if (confLocation == null) { + url = PropertiesUtil.class.getResource("/application.properties"); + } else { + url = new File(confLocation, "application.properties").toURI().toURL(); + } + configuration.load(url); + configuration.setProperty(TLS_ENABLED, true); + configuration.setProperty("metadata.http.authentication.enabled", "true"); + configuration.setProperty("metadata.http.authentication.kerberos.principal", "HTTP/localhost@" + kdc.getRealm()); + configuration.setProperty("metadata.http.authentication.kerberos.keytab", httpKeytabFile.getAbsolutePath()); + configuration.setProperty("metadata.http.authentication.kerberos.name.rules", + "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\nDEFAULT"); + + configuration.save(new FileWriter(persistDir + File.separator + "application.properties")); + + dgiCLient = new MetadataServiceClient(DGI_URL) { + @Override + protected PropertiesConfiguration getClientProperties() throws MetadataException { + return configuration; + } + }; + + secureEmbeddedServer = new TestSecureEmbeddedServer(21443, "webapp/target/metadata-governance") { + @Override + public PropertiesConfiguration getConfiguration() { + return configuration; + } + }; + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(System.getProperty("user.dir") + getWarPath()); + secureEmbeddedServer.getServer().setHandler(webapp); + + // save original setting + originalConf = System.getProperty("metadata.conf"); + System.setProperty("metadata.conf", persistDir); + secureEmbeddedServer.getServer().start(); + + subject = loginTestUser(); + } + + @AfterClass + public void tearDown() throws Exception { + if (secureEmbeddedServer != null) { + secureEmbeddedServer.getServer().stop(); + } + + if (kdc != null) { + kdc.stop(); + } + + if (originalConf != null) { + System.setProperty("metadata.conf", originalConf); + } + } + + protected Subject loginTestUser() throws LoginException, IOException { + LoginContext lc = new LoginContext(TEST_USER_JAAS_SECTION, new CallbackHandler() { + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof PasswordCallback) { + PasswordCallback passwordCallback = (PasswordCallback) callbacks[i]; + passwordCallback.setPassword(TESTPASS.toCharArray()); + } + if (callbacks[i] instanceof NameCallback) { + NameCallback nameCallback = (NameCallback) callbacks[i]; + nameCallback.setName(TESTUSER); + } + } + } + }); + // attempt authentication + lc.login(); + return lc.getSubject(); + } + + private void runCommand(final String cmd) throws Exception { + ss.setCommandType(null); + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { + @Override + public Object run() throws Exception { + driver.run(cmd); + + return null; + } + }); + } + + @Test + public void testCreateDatabase() throws Exception { + String dbName = "db" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create database " + dbName); + + assertDatabaseIsRegistered(dbName); + } + + @Test + public void testCreateTable() throws Exception { + String dbName = "db" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create database " + dbName); + + String tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + dbName + "." + tableName + "(id int, name string)"); + assertTableIsRegistered(tableName); + + tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + tableName + "(id int, name string)"); + assertTableIsRegistered(tableName); + + //Create table where database doesn't exist, will create database instance as well + assertDatabaseIsRegistered("default"); + } + + @Test + public void testCTAS() throws Exception { + String tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + tableName + "(id int, name string)"); + + String newTableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + String query = "create table " + newTableName + " as select * from " + tableName; + runCommand(query); + + assertTableIsRegistered(newTableName); + assertInstanceIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), "queryText", query); + } + + private void assertTableIsRegistered(String tableName) throws Exception { + assertInstanceIsRegistered(HiveDataTypes.HIVE_TABLE.getName(), "tableName", tableName); + } + + private void assertDatabaseIsRegistered(String dbName) throws Exception { + assertInstanceIsRegistered(HiveDataTypes.HIVE_DB.getName(), "name", dbName); + } + + private void assertInstanceIsRegistered(final String typeName, final String colName, final String colValue) throws Exception { + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { + @Override + public Object run() throws Exception { + JSONArray results = dgiCLient.rawSearch(typeName, colName, colValue); + Assert.assertEquals(results.length(), 1); + + return null; + } + }); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLHiveHookIT.java ---------------------------------------------------------------------- diff --git a/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLHiveHookIT.java b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLHiveHookIT.java new file mode 100755 index 0000000..8ef9de7 --- /dev/null +++ b/addons/hive-bridge/src/test/java/org/apache/hadoop/metadata/hive/hook/SSLHiveHookIT.java @@ -0,0 +1,253 @@ +/** + * 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.hadoop.metadata.hive.hook; + +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.metadata.MetadataException; +import org.apache.hadoop.metadata.MetadataServiceClient; +import org.apache.hadoop.metadata.hive.bridge.HiveMetaStoreBridge; +import org.apache.hadoop.metadata.hive.model.HiveDataTypes; +import org.apache.hadoop.metadata.security.SecurityProperties; +import org.apache.hadoop.metadata.web.service.SecureEmbeddedServer; +import org.apache.hadoop.security.alias.CredentialProvider; +import org.apache.hadoop.security.alias.CredentialProviderFactory; +import org.apache.hadoop.security.alias.JavaKeyStoreProvider; +import org.apache.hadoop.security.ssl.SSLFactory; +import org.apache.hadoop.security.ssl.SSLHostnameVerifier; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.webapp.WebAppContext; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; + +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + +public class SSLHiveHookIT { + private static final String DGI_URL = "https://localhost:21443/"; + private Driver driver; + private MetadataServiceClient dgiCLient; + private SessionState ss; + private Path jksPath; + private String providerUrl; + private TestSecureEmbeddedServer secureEmbeddedServer; + + class TestSecureEmbeddedServer extends SecureEmbeddedServer { + + public TestSecureEmbeddedServer(int port, String path) throws IOException { + super(port, path); + } + + public Server getServer () { return server; } + + @Override + public PropertiesConfiguration getConfiguration() { + return super.getConfiguration(); + } + } + + @BeforeClass + public void setUp() throws Exception { + //Set-up hive session + HiveConf conf = getHiveConf(); + driver = new Driver(conf); + ss = new SessionState(conf, System.getProperty("user.name")); + ss = SessionState.start(ss); + SessionState.setCurrentSessionState(ss); + + jksPath = new Path(Files.createTempDirectory("tempproviders").toString(), "test.jks"); + providerUrl = JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri(); + + String persistDir = null; + URL resource = SSLHiveHookIT.class.getResource("/"); + if (resource != null) { + persistDir = resource.toURI().getPath(); + } + // delete prior ssl-client.xml file + resource = SSLHiveHookIT.class.getResource("/" + SecurityProperties.SSL_CLIENT_PROPERTIES); + if (resource != null) { + File sslClientFile = new File(persistDir, SecurityProperties.SSL_CLIENT_PROPERTIES); + if (sslClientFile != null && sslClientFile.exists()) { + sslClientFile.delete(); + } + } + setupCredentials(); + + final PropertiesConfiguration configuration = new PropertiesConfiguration(); + configuration.setProperty(TLS_ENABLED, true); + configuration.setProperty(TRUSTSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(KEYSTORE_FILE_KEY, "../../webapp/target/metadata.keystore"); + configuration.setProperty(CERT_STORES_CREDENTIAL_PROVIDER_PATH, providerUrl); + configuration.setProperty(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, SSLHostnameVerifier.DEFAULT_AND_LOCALHOST.toString()); + + configuration.save(new FileWriter(persistDir + File.separator + "client.properties")); + + dgiCLient = new MetadataServiceClient(DGI_URL) { + @Override + protected PropertiesConfiguration getClientProperties() throws MetadataException { + return configuration; + } + }; + + secureEmbeddedServer = new TestSecureEmbeddedServer(21443, "webapp/target/metadata-governance") { + @Override + public PropertiesConfiguration getConfiguration() { + return configuration; + } + }; + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(System.getProperty("user.dir") + getWarPath()); + secureEmbeddedServer.getServer().setHandler(webapp); + + secureEmbeddedServer.getServer().start(); + + } + + @AfterClass + public void tearDown() throws Exception { + if (secureEmbeddedServer != null) { + secureEmbeddedServer.getServer().stop(); + } + } + + protected void setupCredentials() throws Exception { + Configuration conf = new Configuration(false); + + File file = new File(jksPath.toUri().getPath()); + file.delete(); + conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, providerUrl); + + CredentialProvider provider = + CredentialProviderFactory.getProviders(conf).get(0); + + // create new aliases + try { + + char[] storepass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + KEYSTORE_PASSWORD_KEY, storepass); + + char[] trustpass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + TRUSTSTORE_PASSWORD_KEY, trustpass); + + char[] trustpass2 = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + "ssl.client.truststore.password", trustpass2); + + char[] certpass = {'k', 'e', 'y', 'p', 'a', 's', 's'}; + provider.createCredentialEntry( + SERVER_CERT_PASSWORD_KEY, certpass); + + // write out so that it can be found in checks + provider.flush(); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + protected String getWarPath() { + return String.format("/../../webapp/target/metadata-webapp-%s", + System.getProperty("project.version", "0.1-incubating-SNAPSHOT")); + } + + private HiveConf getHiveConf() { + HiveConf hiveConf = new HiveConf(this.getClass()); + hiveConf.setVar(HiveConf.ConfVars.PREEXECHOOKS, ""); + hiveConf.setVar(HiveConf.ConfVars.POSTEXECHOOKS, HiveHook.class.getName()); + hiveConf.setBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY, false); + hiveConf.setVar(HiveConf.ConfVars.METASTOREWAREHOUSE, System.getProperty("user.dir") + "/target/metastore"); + hiveConf.set(HiveMetaStoreBridge.DGI_URL_PROPERTY, DGI_URL); + hiveConf.set("javax.jdo.option.ConnectionURL", "jdbc:derby:./target/metastore_db;create=true"); + hiveConf.set("hive.hook.dgi.synchronous", "true"); + return hiveConf; + } + + private void runCommand(String cmd) throws Exception { + ss.setCommandType(null); + driver.run(cmd); + } + + @Test + public void testCreateDatabase() throws Exception { + String dbName = "db" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create database " + dbName); + + assertDatabaseIsRegistered(dbName); + } + + @Test + public void testCreateTable() throws Exception { + String dbName = "db" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create database " + dbName); + + String tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + dbName + "." + tableName + "(id int, name string)"); + assertTableIsRegistered(tableName); + + tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + tableName + "(id int, name string)"); + assertTableIsRegistered(tableName); + + //Create table where database doesn't exist, will create database instance as well + assertDatabaseIsRegistered("default"); + } + + @Test + public void testCTAS() throws Exception { + String tableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + runCommand("create table " + tableName + "(id int, name string)"); + + String newTableName = "table" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + String query = "create table " + newTableName + " as select * from " + tableName; + runCommand(query); + + assertTableIsRegistered(newTableName); + assertInstanceIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), "queryText", query); + } + + private void assertTableIsRegistered(String tableName) throws Exception { + assertInstanceIsRegistered(HiveDataTypes.HIVE_TABLE.getName(), "tableName", tableName); + } + + private void assertDatabaseIsRegistered(String dbName) throws Exception { + assertInstanceIsRegistered(HiveDataTypes.HIVE_DB.getName(), "name", dbName); + } + + private void assertInstanceIsRegistered(String typeName, String colName, String colValue) throws Exception{ + JSONArray results = dgiCLient.rawSearch(typeName, colName, colValue); + Assert.assertEquals(results.length(), 1); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/pom.xml ---------------------------------------------------------------------- diff --git a/client/pom.xml b/client/pom.xml index cdfbecc..6d75915 100755 --- a/client/pom.xml +++ b/client/pom.xml @@ -38,13 +38,78 @@ </dependency> <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-minikdc</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.directory.jdbm</groupId> + <artifactId>apacheds-jdbm1</artifactId> + <version>2.0.0-M2</version> + <scope>test</scope> + </dependency> + + <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> </dependency> <dependency> + <groupId>commons-configuration</groupId> + <artifactId>commons-configuration</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-common</artifactId> + <version>${hadoop.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-annotations</artifactId> + <version>${hadoop.version}</version> + </dependency> + + <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> </dependency> </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.2</version> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <inherited>true</inherited> + <extensions>true</extensions> + </plugin> + </plugins> + </build> + </project> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/src/main/java/org/apache/hadoop/metadata/MetadataServiceClient.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/hadoop/metadata/MetadataServiceClient.java b/client/src/main/java/org/apache/hadoop/metadata/MetadataServiceClient.java index 9379aa5..5cb4584 100755 --- a/client/src/main/java/org/apache/hadoop/metadata/MetadataServiceClient.java +++ b/client/src/main/java/org/apache/hadoop/metadata/MetadataServiceClient.java @@ -22,13 +22,16 @@ import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.client.urlconnection.URLConnectionClientHandler; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.hadoop.metadata.security.SecureClientUtils; import org.apache.hadoop.metadata.typesystem.ITypedReferenceableInstance; -import org.apache.hadoop.metadata.typesystem.Referenceable; -import org.apache.hadoop.metadata.typesystem.json.InstanceSerialization; import org.apache.hadoop.metadata.typesystem.json.Serialization; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.MediaType; @@ -37,25 +40,45 @@ import javax.ws.rs.core.UriBuilder; import java.util.ArrayList; import java.util.List; +import static org.apache.hadoop.metadata.security.SecurityProperties.TLS_ENABLED; + /** * Client for metadata. */ public class MetadataServiceClient { + private static final Logger LOG = LoggerFactory.getLogger(MetadataServiceClient.class); public static final String REQUEST_ID = "requestId"; public static final String RESULTS = "results"; public static final String TOTAL_SIZE = "totalSize"; - private final WebResource service; + private WebResource service; public MetadataServiceClient(String baseUrl) { DefaultClientConfig config = new DefaultClientConfig(); - Client client = Client.create(config); + PropertiesConfiguration clientConfig = null; + try { + clientConfig = getClientProperties(); + if (clientConfig.getBoolean(TLS_ENABLED) || clientConfig.getString("metadata.http.authentication.type") != null) { + // create an SSL properties configuration if one doesn't exist. SSLFactory expects a file, so forced to create a + // configuration object, persist it, then subsequently pass in an empty configuration to SSLFactory + SecureClientUtils.persistSSLClientConfiguration(clientConfig); + } + } catch (Exception e) { + LOG.info("Error processing client configuration.", e); + } + URLConnectionClientHandler handler = SecureClientUtils.getClientConnectionHandler(config, clientConfig); + + Client client = new Client(handler, config); client.resource(UriBuilder.fromUri(baseUrl).build()); service = client.resource(UriBuilder.fromUri(baseUrl).build()); } + protected PropertiesConfiguration getClientProperties() throws MetadataException { + return PropertiesUtil.getClientProperties(); + } + static enum API { //Type operations CREATE_TYPE("api/metadata/types/submit", HttpMethod.POST), http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java b/client/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java new file mode 100644 index 0000000..7e69377 --- /dev/null +++ b/client/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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.hadoop.metadata; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +public class PropertiesUtil { + private static final Logger LOG = LoggerFactory.getLogger(PropertiesUtil.class); + + private static final String APPLICATION_PROPERTIES = "application.properties"; + public static final String CLIENT_PROPERTIES = "client.properties"; + + public static final PropertiesConfiguration getApplicationProperties() throws MetadataException { + return getPropertiesConfiguration(APPLICATION_PROPERTIES); + } + + public static final PropertiesConfiguration getClientProperties() throws MetadataException { + return getPropertiesConfiguration(CLIENT_PROPERTIES); + } + + private static PropertiesConfiguration getPropertiesConfiguration(String name) throws MetadataException { + String confLocation = System.getProperty("metadata.conf"); + URL url; + try { + if (confLocation == null) { + url = PropertiesUtil.class.getResource("/" + name); + } else { + url = new File(confLocation, name).toURI().toURL(); + } + LOG.info("Loading {} from {}", name, url); + return new PropertiesConfiguration(url); + } catch (Exception e) { + throw new MetadataException("Failed to load application properties", e); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/src/main/java/org/apache/hadoop/metadata/security/SecureClientUtils.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/hadoop/metadata/security/SecureClientUtils.java b/client/src/main/java/org/apache/hadoop/metadata/security/SecureClientUtils.java new file mode 100644 index 0000000..7755b82 --- /dev/null +++ b/client/src/main/java/org/apache/hadoop/metadata/security/SecureClientUtils.java @@ -0,0 +1,195 @@ +/* + * 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.hadoop.metadata.security; + +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.client.urlconnection.HttpURLConnectionFactory; +import com.sun.jersey.client.urlconnection.URLConnectionClientHandler; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.metadata.MetadataException; +import org.apache.hadoop.metadata.PropertiesUtil; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.alias.CredentialProviderFactory; +import org.apache.hadoop.security.authentication.client.AuthenticationException; +import org.apache.hadoop.security.authentication.client.Authenticator; +import org.apache.hadoop.security.authentication.client.ConnectionConfigurator; +import org.apache.hadoop.security.ssl.SSLFactory; +import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticatedURL; +import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticator; +import org.apache.hadoop.security.token.delegation.web.KerberosDelegationTokenAuthenticator; +import org.apache.hadoop.security.token.delegation.web.PseudoDelegationTokenAuthenticator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.security.GeneralSecurityException; +import java.security.PrivilegedExceptionAction; + +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + +/** + * + */ +public class SecureClientUtils { + + public final static int DEFAULT_SOCKET_TIMEOUT = 1 * 60 * 1000; // 1 minute + private static final Logger LOG = LoggerFactory.getLogger(SecureClientUtils.class); + + + public static URLConnectionClientHandler getClientConnectionHandler(DefaultClientConfig config, + PropertiesConfiguration clientConfig) { + config.getProperties().put( + URLConnectionClientHandler.PROPERTY_HTTP_URL_CONNECTION_SET_METHOD_WORKAROUND, + true); + Configuration conf = new Configuration(false); + conf.addResource(conf.get(SSLFactory.SSL_CLIENT_CONF_KEY, "ssl-client.xml")); + String authType = "simple"; + if (clientConfig != null) { + authType = clientConfig.getString("metadata.http.authentication.type", "simple"); + } + UserGroupInformation.setConfiguration(conf); + final ConnectionConfigurator connConfigurator = newConnConfigurator(conf); + Authenticator authenticator = new PseudoDelegationTokenAuthenticator(); + if (!authType.equals("simple")) { + authenticator = new KerberosDelegationTokenAuthenticator(); + } + authenticator.setConnectionConfigurator(connConfigurator); + final DelegationTokenAuthenticator finalAuthenticator = (DelegationTokenAuthenticator) authenticator; + final DelegationTokenAuthenticatedURL.Token token = new DelegationTokenAuthenticatedURL.Token(); + HttpURLConnectionFactory httpURLConnectionFactory = new HttpURLConnectionFactory() { + @Override + public HttpURLConnection getHttpURLConnection(final URL url) throws IOException { + try { + return new DelegationTokenAuthenticatedURL(finalAuthenticator, connConfigurator) + .openConnection(url, token, null); + } catch (Exception e) { + throw new IOException(e); + } + } + }; + + return new URLConnectionClientHandler(httpURLConnectionFactory); + } + + private final static ConnectionConfigurator DEFAULT_TIMEOUT_CONN_CONFIGURATOR = + new ConnectionConfigurator() { + @Override + public HttpURLConnection configure(HttpURLConnection conn) + throws IOException { + setTimeouts(conn, DEFAULT_SOCKET_TIMEOUT); + return conn; + } + }; + + private static ConnectionConfigurator newConnConfigurator(Configuration conf) { + try { + return newSslConnConfigurator(DEFAULT_SOCKET_TIMEOUT, conf); + } catch (Exception e) { + LOG.debug("Cannot load customized ssl related configuration. " + + "Fallback to system-generic settings.", e); + return DEFAULT_TIMEOUT_CONN_CONFIGURATOR; + } + } + + private static ConnectionConfigurator newSslConnConfigurator(final int timeout, + Configuration conf) throws IOException, GeneralSecurityException { + final SSLFactory factory; + final SSLSocketFactory sf; + final HostnameVerifier hv; + + factory = new SSLFactory(SSLFactory.Mode.CLIENT, conf); + factory.init(); + sf = factory.createSSLSocketFactory(); + hv = factory.getHostnameVerifier(); + + return new ConnectionConfigurator() { + @Override + public HttpURLConnection configure(HttpURLConnection conn) + throws IOException { + if (conn instanceof HttpsURLConnection) { + HttpsURLConnection c = (HttpsURLConnection) conn; + c.setSSLSocketFactory(sf); + c.setHostnameVerifier(hv); + } + setTimeouts(conn, timeout); + return conn; + } + }; + } + + private static void setTimeouts(URLConnection connection, int socketTimeout) { + connection.setConnectTimeout(socketTimeout); + connection.setReadTimeout(socketTimeout); + } + + private static File getSSLClientFile() throws MetadataException { + String confLocation = System.getProperty("metadata.conf"); + File sslDir; + try { + if (confLocation == null) { + String persistDir = null; + URL resource = PropertiesUtil.class.getResource("/"); + if (resource != null) { + persistDir = resource.toURI().getPath(); + } + assert persistDir != null; + sslDir = new File(persistDir); + } else { + sslDir = new File(confLocation); + } + LOG.info("ssl-client.xml will be created in {}", sslDir); + } catch (Exception e) { + throw new MetadataException("Failed to find client configuration directory", e); + } + return new File(sslDir, SecurityProperties.SSL_CLIENT_PROPERTIES); + } + + public static void persistSSLClientConfiguration(PropertiesConfiguration clientConfig) throws MetadataException, IOException { + //trust settings + Configuration configuration = new Configuration(false); + File sslClientFile = getSSLClientFile(); + if (!sslClientFile.exists()) { + configuration.set("ssl.client.truststore.type", "jks"); + configuration.set("ssl.client.truststore.location", clientConfig.getString(TRUSTSTORE_FILE_KEY)); + if (clientConfig.getBoolean(CLIENT_AUTH_KEY, false)) { + // need to get client key properties + configuration.set("ssl.client.keystore.location", clientConfig.getString(KEYSTORE_FILE_KEY)); + configuration.set("ssl.client.keystore.type", "jks"); + } + // add the configured credential provider + configuration.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, + clientConfig.getString(CERT_STORES_CREDENTIAL_PROVIDER_PATH)); + String hostnameVerifier = clientConfig.getString(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY); + if (hostnameVerifier != null) { + configuration.set(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, hostnameVerifier); + } + + configuration.writeXml(new FileWriter(sslClientFile)); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/src/main/java/org/apache/hadoop/metadata/security/SecurityProperties.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/hadoop/metadata/security/SecurityProperties.java b/client/src/main/java/org/apache/hadoop/metadata/security/SecurityProperties.java new file mode 100644 index 0000000..8cfff8e --- /dev/null +++ b/client/src/main/java/org/apache/hadoop/metadata/security/SecurityProperties.java @@ -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. + */ +package org.apache.hadoop.metadata.security; + +/** + * + */ +public interface SecurityProperties { + public static final String TLS_ENABLED = "metadata.enableTLS"; + public static final String KEYSTORE_FILE_KEY = "keystore.file"; + public static final String DEFAULT_KEYSTORE_FILE_LOCATION = "target/metadata.keystore"; + public static final String KEYSTORE_PASSWORD_KEY = "keystore.password"; + public static final String TRUSTSTORE_FILE_KEY = "truststore.file"; + public static final String DEFATULT_TRUSTORE_FILE_LOCATION = "target/metadata.keystore"; + public static final String TRUSTSTORE_PASSWORD_KEY = "truststore.password"; + public static final String SERVER_CERT_PASSWORD_KEY = "password"; + public static final String CLIENT_AUTH_KEY = "client.auth.enabled"; + public static final String CERT_STORES_CREDENTIAL_PROVIDER_PATH = "cert.stores.credential.provider.path"; + String SSL_CLIENT_PROPERTIES = "ssl-client.xml"; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/client/src/test/java/org/apache/hadoop/metadata/security/BaseSecurityTest.java ---------------------------------------------------------------------- diff --git a/client/src/test/java/org/apache/hadoop/metadata/security/BaseSecurityTest.java b/client/src/test/java/org/apache/hadoop/metadata/security/BaseSecurityTest.java new file mode 100644 index 0000000..ac099e8 --- /dev/null +++ b/client/src/test/java/org/apache/hadoop/metadata/security/BaseSecurityTest.java @@ -0,0 +1,128 @@ +/* + * 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.hadoop.metadata.security; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.hadoop.minikdc.MiniKdc; +import org.apache.zookeeper.Environment; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.webapp.WebAppContext; +import org.testng.Assert; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.util.Locale; +import java.util.Properties; + +/** + * + */ +public class BaseSecurityTest { + private static final String JAAS_ENTRY = + "%s { \n" + + " %s required\n" + // kerberos module + + " keyTab=\"%s\"\n" + + " debug=true\n" + + " principal=\"%s\"\n" + + " useKeyTab=true\n" + + " useTicketCache=false\n" + + " doNotPrompt=true\n" + + " storeKey=true;\n" + + "}; \n"; + protected MiniKdc kdc; + + protected String getWarPath() { + return String.format("/target/metadata-webapp-%s.war", + System.getProperty("release.version", "0.1-incubating-SNAPSHOT")); + } + + protected void generateTestProperties(Properties props) throws ConfigurationException, IOException { + PropertiesConfiguration config = new PropertiesConfiguration(System.getProperty("user.dir") + + "/../src/conf/application.properties"); + for (String propName : props.stringPropertyNames()) { + config.setProperty(propName, props.getProperty(propName)); + } + File file = new File(System.getProperty("user.dir"), "application.properties"); + file.deleteOnExit(); + Writer fileWriter = new FileWriter(file); + config.save(fileWriter); + } + + protected void startEmbeddedServer(Server server) throws Exception { + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(System.getProperty("user.dir") + getWarPath()); + server.setHandler(webapp); + + server.start(); + } + + protected File startKDC() throws Exception { + File target = Files.createTempDirectory("sectest").toFile(); + File kdcWorkDir = new File(target, "kdc"); + Properties kdcConf = MiniKdc.createConf(); + kdcConf.setProperty(MiniKdc.DEBUG, "true"); + kdc = new MiniKdc(kdcConf, kdcWorkDir); + kdc.start(); + + Assert.assertNotNull(kdc.getRealm()); + return kdcWorkDir; + } + + public String createJAASEntry( + String context, + String principal, + File keytab) { + String keytabpath = keytab.getAbsolutePath(); + // fix up for windows; no-op on unix + keytabpath = keytabpath.replace('\\', '/'); + return String.format( + Locale.ENGLISH, + JAAS_ENTRY, + context, + getKerberosAuthModuleForJVM(), + keytabpath, + principal); + } + + protected String getKerberosAuthModuleForJVM() { + if (System.getProperty("java.vendor").contains("IBM")) { + return "com.ibm.security.auth.module.Krb5LoginModule"; + } else { + return "com.sun.security.auth.module.Krb5LoginModule"; + } + } + + protected void bindJVMtoJAASFile(File jaasFile) { + String path = jaasFile.getAbsolutePath(); + System.setProperty(Environment.JAAS_CONF_KEY, path); + } + + protected File createKeytab(MiniKdc kdc, File kdcWorkDir, String principal, String filename) throws Exception { + File keytab = new File(kdcWorkDir, filename); + kdc.createPrincipal(keytab, + principal, + principal + "/localhost", + principal + "/127.0.0.1"); + return keytab; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 0ac2c2a..91a8430 100755 --- a/pom.xml +++ b/pom.xml @@ -823,7 +823,9 @@ <!--<skipTests>true</skipTests>--> <forkMode>always</forkMode> <redirectTestOutputToFile>true</redirectTestOutputToFile> - <argLine>-Djava.awt.headless=true</argLine> + <argLine>-Djava.awt.headless=true -Dproject.version=${project.version} + -Dhadoop.tmp.dir=${project.build.directory}/tmp-hadoop-${user.name} + -Xmx1024m -XX:MaxPermSize=512m</argLine> </configuration> <dependencies> <dependency> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/repository/pom.xml ---------------------------------------------------------------------- diff --git a/repository/pom.xml b/repository/pom.xml index 7003ad2..c626962 100755 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -40,6 +40,11 @@ </dependency> <dependency> + <groupId>org.apache.hadoop.metadata</groupId> + <artifactId>metadata-client</artifactId> + </dependency> + + <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/repository/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java b/repository/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java deleted file mode 100644 index d30c4cc..0000000 --- a/repository/src/main/java/org/apache/hadoop/metadata/PropertiesUtil.java +++ /dev/null @@ -1,50 +0,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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.hadoop.metadata; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -public class PropertiesUtil { - private static final Logger LOG = LoggerFactory.getLogger(PropertiesUtil.class); - - private static final String APPLICATION_PROPERTIES = "application.properties"; - - public static final PropertiesConfiguration getApplicationProperties() throws MetadataException { - String confLocation = System.getProperty("metadata.conf"); - URL url; - try { - if (confLocation == null) { - url = PropertiesUtil.class.getResource("/" + APPLICATION_PROPERTIES); - } else { - url = new File(confLocation, APPLICATION_PROPERTIES).toURI().toURL(); - } - LOG.info("Loading {} from {}", APPLICATION_PROPERTIES, url); - return new PropertiesConfiguration(url); - } catch (Exception e) { - throw new MetadataException("Failed to load application properties", e); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/pom.xml ---------------------------------------------------------------------- diff --git a/webapp/pom.xml b/webapp/pom.xml index 6a66bea..2e56689 100755 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -48,9 +48,17 @@ <artifactId>metadata-repository</artifactId> </dependency> + <!--<dependency>--> + <!--<groupId>org.apache.hadoop.metadata</groupId>--> + <!--<artifactId>metadata-client</artifactId>--> + <!--</dependency>--> + <dependency> <groupId>org.apache.hadoop.metadata</groupId> <artifactId>metadata-client</artifactId> + <version>${version}</version> + <type>test-jar</type> + <scope>test</scope> </dependency> <dependency> @@ -214,6 +222,7 @@ <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> + <attachClasses>true</attachClasses> <webResources> <resource> <directory>../dashboard/v3</directory> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/src/main/java/org/apache/hadoop/metadata/util/CredentialProviderUtility.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/hadoop/metadata/util/CredentialProviderUtility.java b/webapp/src/main/java/org/apache/hadoop/metadata/util/CredentialProviderUtility.java index 158e191..a91db75 100755 --- a/webapp/src/main/java/org/apache/hadoop/metadata/util/CredentialProviderUtility.java +++ b/webapp/src/main/java/org/apache/hadoop/metadata/util/CredentialProviderUtility.java @@ -26,13 +26,15 @@ import org.apache.hadoop.security.alias.JavaKeyStoreProvider; import java.io.*; import java.util.Arrays; +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + /** * A utility class for generating a credential provider containing the entries required for supporting the SSL implementation * of the DGC server. */ public class CredentialProviderUtility { - private static final String[] KEYS = new String[] {SecureEmbeddedServer.KEYSTORE_PASSWORD_KEY, - SecureEmbeddedServer.TRUSTSTORE_PASSWORD_KEY, SecureEmbeddedServer.SERVER_CERT_PASSWORD_KEY}; + private static final String[] KEYS = new String[] {KEYSTORE_PASSWORD_KEY, + TRUSTSTORE_PASSWORD_KEY, SERVER_CERT_PASSWORD_KEY}; public static abstract class TextDevice { public abstract void printf(String fmt, Object... params); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/src/main/java/org/apache/hadoop/metadata/web/filters/MetadataAuthenticationFilter.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/hadoop/metadata/web/filters/MetadataAuthenticationFilter.java b/webapp/src/main/java/org/apache/hadoop/metadata/web/filters/MetadataAuthenticationFilter.java index cd79f63..3874d25 100644 --- a/webapp/src/main/java/org/apache/hadoop/metadata/web/filters/MetadataAuthenticationFilter.java +++ b/webapp/src/main/java/org/apache/hadoop/metadata/web/filters/MetadataAuthenticationFilter.java @@ -21,6 +21,7 @@ package org.apache.hadoop.metadata.web.filters; import com.google.inject.Singleton; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.hadoop.metadata.PropertiesUtil; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.authentication.server.AuthenticationFilter; import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler; @@ -49,8 +50,8 @@ public class MetadataAuthenticationFilter extends AuthenticationFilter { protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) throws ServletException { PropertiesConfiguration configuration; try { - configuration = new PropertiesConfiguration("application.properties"); - } catch (ConfigurationException e) { + configuration = PropertiesUtil.getApplicationProperties(); + } catch (Exception e) { throw new ServletException(e); } @@ -95,6 +96,8 @@ public class MetadataAuthenticationFilter extends AuthenticationFilter { config.put(KerberosAuthenticationHandler.PRINCIPAL, principal); } + LOG.info("AuthenticationFilterConfig: {}", config); + return config; } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/src/main/java/org/apache/hadoop/metadata/web/listeners/GuiceServletConfig.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/hadoop/metadata/web/listeners/GuiceServletConfig.java b/webapp/src/main/java/org/apache/hadoop/metadata/web/listeners/GuiceServletConfig.java index 92947d2..b7eeda4 100755 --- a/webapp/src/main/java/org/apache/hadoop/metadata/web/listeners/GuiceServletConfig.java +++ b/webapp/src/main/java/org/apache/hadoop/metadata/web/listeners/GuiceServletConfig.java @@ -27,6 +27,7 @@ import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.hadoop.metadata.MetadataException; +import org.apache.hadoop.metadata.PropertiesUtil; import org.apache.hadoop.metadata.RepositoryMetadataModule; import org.apache.hadoop.metadata.repository.typestore.ITypeStore; import org.apache.hadoop.metadata.typesystem.TypesDef; @@ -80,10 +81,13 @@ public class GuiceServletConfig extends GuiceServletContextListener { } private void configureAuthenticationFilter() throws ConfigurationException { - PropertiesConfiguration configuration = - new PropertiesConfiguration("application.properties"); - if (Boolean.valueOf(configuration.getString(HTTP_AUTHENTICATION_ENABLED))) { - filter("/*").through(MetadataAuthenticationFilter.class); + try { + PropertiesConfiguration configuration = PropertiesUtil.getApplicationProperties(); + if (Boolean.valueOf(configuration.getString(HTTP_AUTHENTICATION_ENABLED))) { + filter("/*").through(MetadataAuthenticationFilter.class); + } + } catch (MetadataException e) { + LOG.warn("Error loading configuration and initializing authentication filter", e); } } }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/src/main/java/org/apache/hadoop/metadata/web/service/SecureEmbeddedServer.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/hadoop/metadata/web/service/SecureEmbeddedServer.java b/webapp/src/main/java/org/apache/hadoop/metadata/web/service/SecureEmbeddedServer.java index 865bc4f..6e71366 100755 --- a/webapp/src/main/java/org/apache/hadoop/metadata/web/service/SecureEmbeddedServer.java +++ b/webapp/src/main/java/org/apache/hadoop/metadata/web/service/SecureEmbeddedServer.java @@ -28,23 +28,16 @@ import org.mortbay.jetty.security.SslSocketConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import java.io.IOException; +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + /** * This is a jetty server which requires client auth via certificates. */ public class SecureEmbeddedServer extends EmbeddedServer { - public static final String KEYSTORE_FILE_KEY = "keystore.file"; - public static final String DEFAULT_KEYSTORE_FILE_LOCATION = "target/metadata.keystore"; - public static final String KEYSTORE_PASSWORD_KEY = "keystore.password"; - public static final String TRUSTSTORE_FILE_KEY = "truststore.file"; - public static final String DEFATULT_TRUSTORE_FILE_LOCATION = "target/metadata.keystore"; - public static final String TRUSTSTORE_PASSWORD_KEY = "truststore.password"; - public static final String SERVER_CERT_PASSWORD_KEY = "password"; - public static final String CLIENT_AUTH_KEY = "client.auth.enabled"; - public static final String CERT_STORES_CREDENTIAL_PROVIDER_PATH = "cert.stores.credential.provider.path"; - private static final Logger LOG = LoggerFactory.getLogger(SecureEmbeddedServer.class); public SecureEmbeddedServer(int port, String path) throws IOException { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/43868812/webapp/src/test/java/org/apache/hadoop/metadata/CredentialProviderUtilityIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/hadoop/metadata/CredentialProviderUtilityIT.java b/webapp/src/test/java/org/apache/hadoop/metadata/CredentialProviderUtilityIT.java index 518615f..1ae733f 100755 --- a/webapp/src/test/java/org/apache/hadoop/metadata/CredentialProviderUtilityIT.java +++ b/webapp/src/test/java/org/apache/hadoop/metadata/CredentialProviderUtilityIT.java @@ -31,6 +31,8 @@ import java.io.IOException; import java.nio.file.Files; import java.util.*; +import static org.apache.hadoop.metadata.security.SecurityProperties.*; + /** * */ @@ -75,11 +77,11 @@ public class CredentialProviderUtilityIT { CredentialProviderFactory.getProviders(conf).get(0); CredentialProvider.CredentialEntry entry = - provider.getCredentialEntry(SecureEmbeddedServer.KEYSTORE_PASSWORD_KEY); + provider.getCredentialEntry(KEYSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.TRUSTSTORE_PASSWORD_KEY); + entry = provider.getCredentialEntry(TRUSTSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.SERVER_CERT_PASSWORD_KEY); + entry = provider.getCredentialEntry(SERVER_CERT_PASSWORD_KEY); assertCredentialEntryCorrect(entry); } @@ -138,11 +140,11 @@ public class CredentialProviderUtilityIT { CredentialProviderFactory.getProviders(conf).get(0); CredentialProvider.CredentialEntry entry = - provider.getCredentialEntry(SecureEmbeddedServer.KEYSTORE_PASSWORD_KEY); + provider.getCredentialEntry(KEYSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.TRUSTSTORE_PASSWORD_KEY); + entry = provider.getCredentialEntry(TRUSTSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.SERVER_CERT_PASSWORD_KEY); + entry = provider.getCredentialEntry(SERVER_CERT_PASSWORD_KEY); assertCredentialEntryCorrect(entry); } @@ -192,11 +194,11 @@ public class CredentialProviderUtilityIT { CredentialProviderFactory.getProviders(conf).get(0); CredentialProvider.CredentialEntry entry = - provider.getCredentialEntry(SecureEmbeddedServer.KEYSTORE_PASSWORD_KEY); + provider.getCredentialEntry(KEYSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.TRUSTSTORE_PASSWORD_KEY); + entry = provider.getCredentialEntry(TRUSTSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry); - entry = provider.getCredentialEntry(SecureEmbeddedServer.SERVER_CERT_PASSWORD_KEY); + entry = provider.getCredentialEntry(SERVER_CERT_PASSWORD_KEY); assertCredentialEntryCorrect(entry); } @@ -260,11 +262,11 @@ public class CredentialProviderUtilityIT { char[] newpass = "newpass".toCharArray(); CredentialProvider.CredentialEntry entry = - provider.getCredentialEntry(SecureEmbeddedServer.KEYSTORE_PASSWORD_KEY); + provider.getCredentialEntry(KEYSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry, newpass); - entry = provider.getCredentialEntry(SecureEmbeddedServer.TRUSTSTORE_PASSWORD_KEY); + entry = provider.getCredentialEntry(TRUSTSTORE_PASSWORD_KEY); assertCredentialEntryCorrect(entry, newpass); - entry = provider.getCredentialEntry(SecureEmbeddedServer.SERVER_CERT_PASSWORD_KEY); + entry = provider.getCredentialEntry(SERVER_CERT_PASSWORD_KEY); assertCredentialEntryCorrect(entry, newpass); } }
