diff --git a/hadoop-common-project/hadoop-kms/pom.xml b/hadoop-common-project/hadoop-kms/pom.xml index 629ffdac706..2c225cb18eb 100644 --- a/hadoop-common-project/hadoop-kms/pom.xml +++ b/hadoop-common-project/hadoop-kms/pom.xml @@ -238,7 +238,7 @@ default-war - package + prepare-package war @@ -251,6 +251,29 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + prepare-jar + prepare-package + + jar + + + classes + + + + prepare-test-jar + prepare-package + + test-jar + + + + org.codehaus.mojo findbugs-maven-plugin diff --git a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/MiniKMS.java b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/MiniKMS.java index 195eee86ad2..f64dcf0e1aa 100644 --- a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/MiniKMS.java +++ b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/MiniKMS.java @@ -18,7 +18,9 @@ package org.apache.hadoop.crypto.key.kms.server; import com.google.common.base.Preconditions; +import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.crypto.key.kms.KMSRESTConstants; import org.apache.hadoop.fs.Path; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; @@ -26,7 +28,10 @@ import org.mortbay.jetty.security.SslSocketConnector; import org.mortbay.jetty.webapp.WebAppContext; import java.io.File; +import java.io.FileOutputStream; import java.io.FileWriter; +import java.io.InputStream; +import java.io.OutputStream; import java.io.Writer; import java.net.InetAddress; import java.net.MalformedURLException; @@ -34,6 +39,7 @@ import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.UUID; public class MiniKMS { @@ -140,13 +146,15 @@ public class MiniKMS { } public void start() throws Exception { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, kmsConfDir); File aclsFile = new File(kmsConfDir, "kms-acls.xml"); if (!aclsFile.exists()) { - Configuration acls = new Configuration(false); - Writer writer = new FileWriter(aclsFile); - acls.writeXml(writer); - writer.close(); + InputStream is = cl.getResourceAsStream("mini-kms-acls-default.xml"); + OutputStream os = new FileOutputStream(aclsFile); + IOUtils.copy(is, os); + is.close(); + os.close(); } File coreFile = new File(kmsConfDir, "core-site.xml"); if (!coreFile.exists()) { @@ -161,19 +169,42 @@ public class MiniKMS { kms.set("hadoop.security.key.provider.path", "jceks://file@" + new Path(kmsConfDir, "kms.keystore").toUri()); kms.set("hadoop.kms.authentication.type", "simple"); + kms.setBoolean(KMSConfiguration.KEY_AUTHORIZATION_ENABLE, false); Writer writer = new FileWriter(kmsFile); kms.writeXml(writer); writer.close(); } System.setProperty("log4j.configuration", log4jConfFile); jetty = createJettyServer(keyStore, keyStorePassword); - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - URL url = cl.getResource("kms-webapp"); - if (url == null) { + + // we need to do a special handling for MiniKMS to work when in a dir and + // when in a JAR in the classpath thanks to Jetty way of handling of webapps + // when they are in the a DIR, WAR or JAR. + URL webXmlUrl = cl.getResource("kms-webapp/WEB-INF/web.xml"); + if (webXmlUrl == null) { throw new RuntimeException( "Could not find kms-webapp/ dir in test classpath"); } - WebAppContext context = new WebAppContext(url.getPath(), "/kms"); + boolean webXmlInJar = webXmlUrl.getPath().contains(".jar!/"); + String webappPath; + if (webXmlInJar) { + File webInf = new File("target/" + UUID.randomUUID().toString() + + "/kms-webapp/WEB-INF"); + webInf.mkdirs(); + new File(webInf, "web.xml").delete(); + InputStream is = cl.getResourceAsStream("kms-webapp/WEB-INF/web.xml"); + OutputStream os = new FileOutputStream(new File(webInf, "web.xml")); + IOUtils.copy(is, os); + is.close(); + os.close(); + webappPath = webInf.getParentFile().getAbsolutePath(); + } else { + webappPath = cl.getResource("kms-webapp").getPath(); + } + WebAppContext context = new WebAppContext(webappPath, "/kms"); + if (webXmlInJar) { + context.setClassLoader(cl); + } jetty.addHandler(context); jetty.start(); kmsURL = new URL(getJettyURL(jetty), "kms"); diff --git a/hadoop-common-project/hadoop-kms/src/test/resources/mini-kms-acls-default.xml b/hadoop-common-project/hadoop-kms/src/test/resources/mini-kms-acls-default.xml new file mode 100644 index 00000000000..24a46b86ec4 --- /dev/null +++ b/hadoop-common-project/hadoop-kms/src/test/resources/mini-kms-acls-default.xml @@ -0,0 +1,135 @@ + + + + + + + + + + hadoop.kms.acl.CREATE + * + + ACL for create-key operations. + If the user does is not in the GET ACL, the key material is not returned + as part of the response. + + + + + hadoop.kms.acl.DELETE + * + + ACL for delete-key operations. + + + + + hadoop.kms.acl.ROLLOVER + * + + ACL for rollover-key operations. + If the user does is not in the GET ACL, the key material is not returned + as part of the response. + + + + + hadoop.kms.acl.GET + * + + ACL for get-key-version and get-current-key operations. + + + + + hadoop.kms.acl.GET_KEYS + * + + ACL for get-keys operation. + + + + + hadoop.kms.acl.GET_METADATA + * + + ACL for get-key-metadata an get-keys-metadata operations. + + + + + hadoop.kms.acl.SET_KEY_MATERIAL + * + + Complimentary ACL for CREATE and ROLLOVER operation to allow the client + to provide the key material when creating or rolling a key. + + + + + hadoop.kms.acl.GENERATE_EEK + * + + ACL for generateEncryptedKey CryptoExtension operations + + + + + hadoop.kms.acl.DECRYPT_EEK + * + + ACL for decrypt EncryptedKey CryptoExtension operations + + + + + default.key.acl.MANAGEMENT + * + + default ACL for MANAGEMENT operations for all key acls that are not + explicitly defined. + + + + + default.key.acl.GENERATE_EEK + * + + default ACL for GENERATE_EEK operations for all key acls that are not + explicitly defined. + + + + + default.key.acl.DECRYPT_EEK + * + + default ACL for DECRYPT_EEK operations for all key acls that are not + explicitly defined. + + + + + default.key.acl.READ + * + + default ACL for READ operations for all key acls that are not + explicitly defined. + + + + + diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 1225311ea26..4976938588a 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -464,6 +464,8 @@ Release 2.6.0 - UNRELEASED HDFS-6880. Adding tracing to DataNode data transfer protocol. (iwasakims via cmccabe) + HDFS-7006. Test encryption zones with KMS. (Anthony Young-Garner and tucu) + OPTIMIZATIONS HDFS-6690. Deduplicate xattr names in memory. (wang) diff --git a/hadoop-hdfs-project/hadoop-hdfs/pom.xml b/hadoop-hdfs-project/hadoop-hdfs/pom.xml index ecdd1aeac42..b1707fef000 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/pom.xml +++ b/hadoop-hdfs-project/hadoop-hdfs/pom.xml @@ -185,6 +185,19 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.htrace htrace-core + + org.apache.hadoop + hadoop-kms + classes + jar + test + + + org.apache.hadoop + hadoop-kms + test-jar + test + diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java index 68fc8506526..96f5fcee07d 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java @@ -112,6 +112,11 @@ public class TestEncryptionZones { protected FileSystemTestWrapper fsWrapper; protected FileContextTestWrapper fcWrapper; + protected String getKeyProviderURI() { + return JavaKeyStoreProvider.SCHEME_NAME + "://file" + testRootDir + + "/test.jks"; + } + @Before public void setup() throws Exception { conf = new HdfsConfiguration(); @@ -119,10 +124,7 @@ public class TestEncryptionZones { // Set up java key store String testRoot = fsHelper.getTestRootDir(); testRootDir = new File(testRoot).getAbsoluteFile(); - final Path jksPath = new Path(testRootDir.toString(), "test.jks"); - conf.set(KeyProviderFactory.KEY_PROVIDER_PATH, - JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri() - ); + conf.set(KeyProviderFactory.KEY_PROVIDER_PATH, getKeyProviderURI()); conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_ALWAYS_USE_KEY, true); // Lower the batch size for testing conf.setInt(DFSConfigKeys.DFS_NAMENODE_LIST_ENCRYPTION_ZONES_NUM_RESPONSES, diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZonesWithKMS.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZonesWithKMS.java new file mode 100644 index 00000000000..3a9a89e4a67 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZonesWithKMS.java @@ -0,0 +1,56 @@ +/** + * 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.hdfs; + +import org.apache.hadoop.crypto.key.kms.KMSClientProvider; +import org.apache.hadoop.crypto.key.kms.server.MiniKMS; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; + +import java.io.File; +import java.util.UUID; + +public class TestEncryptionZonesWithKMS extends TestEncryptionZones { + + private MiniKMS miniKMS; + + @Override + protected String getKeyProviderURI() { + return KMSClientProvider.SCHEME_NAME + "://" + + miniKMS.getKMSUrl().toExternalForm().replace("://", "@"); + } + + @Before + public void setup() throws Exception { + File kmsDir = new File("target/test-classes/" + + UUID.randomUUID().toString()); + Assert.assertTrue(kmsDir.mkdirs()); + MiniKMS.Builder miniKMSBuilder = new MiniKMS.Builder(); + miniKMS = miniKMSBuilder.setKmsConfDir(kmsDir).build(); + miniKMS.start(); + super.setup(); + } + + @After + public void teardown() { + super.teardown(); + miniKMS.stop(); + } + +} diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml index 0f662a2049c..a121fafc33f 100644 --- a/hadoop-project/pom.xml +++ b/hadoop-project/pom.xml @@ -334,6 +334,20 @@ ${project.version} + + org.apache.hadoop + hadoop-kms + ${project.version} + classes + jar + + + org.apache.hadoop + hadoop-kms + ${project.version} + test-jar + + com.google.guava guava