|
@@ -17,7 +17,6 @@
|
|
*/
|
|
*/
|
|
package org.apache.hadoop.hdfs.server.namenode;
|
|
package org.apache.hadoop.hdfs.server.namenode;
|
|
|
|
|
|
-import static org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion;
|
|
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_DEFAULT;
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_DEFAULT;
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY;
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY;
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT;
|
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT;
|
|
@@ -102,7 +101,6 @@ import java.io.StringWriter;
|
|
import java.lang.management.ManagementFactory;
|
|
import java.lang.management.ManagementFactory;
|
|
import java.net.InetAddress;
|
|
import java.net.InetAddress;
|
|
import java.net.URI;
|
|
import java.net.URI;
|
|
-import java.security.GeneralSecurityException;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
@@ -115,6 +113,7 @@ import java.util.Iterator;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.Map.Entry;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
import java.util.TreeMap;
|
|
import java.util.TreeMap;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
@@ -132,9 +131,8 @@ import org.apache.commons.logging.impl.Log4JLogger;
|
|
import org.apache.hadoop.HadoopIllegalArgumentException;
|
|
import org.apache.hadoop.HadoopIllegalArgumentException;
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
import org.apache.hadoop.conf.Configuration;
|
|
import org.apache.hadoop.conf.Configuration;
|
|
-import org.apache.hadoop.crypto.CipherSuite;
|
|
|
|
import org.apache.hadoop.crypto.CryptoProtocolVersion;
|
|
import org.apache.hadoop.crypto.CryptoProtocolVersion;
|
|
-import org.apache.hadoop.crypto.key.KeyProvider;
|
|
|
|
|
|
+import org.apache.hadoop.crypto.key.KeyProvider.Metadata;
|
|
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
|
|
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
|
|
import org.apache.hadoop.fs.BatchedRemoteIterator.BatchedListEntries;
|
|
import org.apache.hadoop.fs.BatchedRemoteIterator.BatchedListEntries;
|
|
import org.apache.hadoop.fs.CacheFlag;
|
|
import org.apache.hadoop.fs.CacheFlag;
|
|
@@ -2029,29 +2027,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
.values()));
|
|
.values()));
|
|
}
|
|
}
|
|
|
|
|
|
- /**
|
|
|
|
- * Invoke KeyProvider APIs to generate an encrypted data encryption key for an
|
|
|
|
- * encryption zone. Should not be called with any locks held.
|
|
|
|
- *
|
|
|
|
- * @param ezKeyName key name of an encryption zone
|
|
|
|
- * @return New EDEK, or null if ezKeyName is null
|
|
|
|
- * @throws IOException
|
|
|
|
- */
|
|
|
|
- private EncryptedKeyVersion generateEncryptedDataEncryptionKey(String
|
|
|
|
- ezKeyName) throws IOException {
|
|
|
|
- if (ezKeyName == null) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
- EncryptedKeyVersion edek = null;
|
|
|
|
- try {
|
|
|
|
- edek = provider.generateEncryptedKey(ezKeyName);
|
|
|
|
- } catch (GeneralSecurityException e) {
|
|
|
|
- throw new IOException(e);
|
|
|
|
- }
|
|
|
|
- Preconditions.checkNotNull(edek);
|
|
|
|
- return edek;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Create a new file entry in the namespace.
|
|
* Create a new file entry in the namespace.
|
|
*
|
|
*
|
|
@@ -2137,7 +2112,8 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
|
|
|
// Generate EDEK if necessary while not holding the lock
|
|
// Generate EDEK if necessary while not holding the lock
|
|
if (ezInfo != null) {
|
|
if (ezInfo != null) {
|
|
- ezInfo.edek = generateEncryptedDataEncryptionKey(ezInfo.ezKeyName);
|
|
|
|
|
|
+ ezInfo.edek = FSDirEncryptionZoneOp
|
|
|
|
+ .generateEncryptedDataEncryptionKey(dir, ezInfo.ezKeyName);
|
|
}
|
|
}
|
|
EncryptionFaultInjector.getInstance().startFileAfterGenerateKey();
|
|
EncryptionFaultInjector.getInstance().startFileAfterGenerateKey();
|
|
}
|
|
}
|
|
@@ -6973,74 +6949,34 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
* @throws SafeModeException if the Namenode is in safe mode.
|
|
* @throws SafeModeException if the Namenode is in safe mode.
|
|
*/
|
|
*/
|
|
void createEncryptionZone(final String src, final String keyName,
|
|
void createEncryptionZone(final String src, final String keyName,
|
|
- boolean logRetryCache)
|
|
|
|
- throws IOException, UnresolvedLinkException,
|
|
|
|
- SafeModeException, AccessControlException {
|
|
|
|
|
|
+ boolean logRetryCache) throws IOException, UnresolvedLinkException,
|
|
|
|
+ SafeModeException, AccessControlException {
|
|
try {
|
|
try {
|
|
- if (provider == null) {
|
|
|
|
- throw new IOException(
|
|
|
|
- "Can't create an encryption zone for " + src +
|
|
|
|
- " since no key provider is available.");
|
|
|
|
- }
|
|
|
|
- if (keyName == null || keyName.isEmpty()) {
|
|
|
|
- throw new IOException("Must specify a key name when creating an " +
|
|
|
|
- "encryption zone");
|
|
|
|
- }
|
|
|
|
- KeyProvider.Metadata metadata = provider.getMetadata(keyName);
|
|
|
|
- if (metadata == null) {
|
|
|
|
- /*
|
|
|
|
- * It would be nice if we threw something more specific than
|
|
|
|
- * IOException when the key is not found, but the KeyProvider API
|
|
|
|
- * doesn't provide for that. If that API is ever changed to throw
|
|
|
|
- * something more specific (e.g. UnknownKeyException) then we can
|
|
|
|
- * update this to match it, or better yet, just rethrow the
|
|
|
|
- * KeyProvider's exception.
|
|
|
|
- */
|
|
|
|
- throw new IOException("Key " + keyName + " doesn't exist.");
|
|
|
|
|
|
+ Metadata metadata = FSDirEncryptionZoneOp.ensureKeyIsInitialized(dir,
|
|
|
|
+ keyName, src);
|
|
|
|
+ checkSuperuserPrivilege();
|
|
|
|
+ FSPermissionChecker pc = getPermissionChecker();
|
|
|
|
+ checkOperation(OperationCategory.WRITE);
|
|
|
|
+ final HdfsFileStatus resultingStat;
|
|
|
|
+ writeLock();
|
|
|
|
+ try {
|
|
|
|
+ checkSuperuserPrivilege();
|
|
|
|
+ checkOperation(OperationCategory.WRITE);
|
|
|
|
+ checkNameNodeSafeMode("Cannot create encryption zone on " + src);
|
|
|
|
+ resultingStat = FSDirEncryptionZoneOp.createEncryptionZone(dir, src,
|
|
|
|
+ pc, metadata.getCipher(), keyName, logRetryCache);
|
|
|
|
+ } finally {
|
|
|
|
+ writeUnlock();
|
|
}
|
|
}
|
|
- // If the provider supports pool for EDEKs, this will fill in the pool
|
|
|
|
- provider.warmUpEncryptedKeys(keyName);
|
|
|
|
- createEncryptionZoneInt(src, metadata.getCipher(),
|
|
|
|
- keyName, logRetryCache);
|
|
|
|
|
|
+
|
|
|
|
+ getEditLog().logSync();
|
|
|
|
+ logAuditEvent(true, "createEncryptionZone", src, null, resultingStat);
|
|
} catch (AccessControlException e) {
|
|
} catch (AccessControlException e) {
|
|
logAuditEvent(false, "createEncryptionZone", src);
|
|
logAuditEvent(false, "createEncryptionZone", src);
|
|
throw e;
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void createEncryptionZoneInt(final String srcArg, String cipher,
|
|
|
|
- String keyName, final boolean logRetryCache) throws IOException {
|
|
|
|
- String src = srcArg;
|
|
|
|
- HdfsFileStatus resultingStat = null;
|
|
|
|
- checkSuperuserPrivilege();
|
|
|
|
- final byte[][] pathComponents =
|
|
|
|
- FSDirectory.getPathComponentsForReservedPath(src);
|
|
|
|
- FSPermissionChecker pc = getPermissionChecker();
|
|
|
|
- writeLock();
|
|
|
|
- try {
|
|
|
|
- checkSuperuserPrivilege();
|
|
|
|
- checkOperation(OperationCategory.WRITE);
|
|
|
|
- checkNameNodeSafeMode("Cannot create encryption zone on " + src);
|
|
|
|
- src = dir.resolvePath(pc, src, pathComponents);
|
|
|
|
-
|
|
|
|
- final CipherSuite suite = CipherSuite.convert(cipher);
|
|
|
|
- // For now this is hardcoded, as we only support one method.
|
|
|
|
- final CryptoProtocolVersion version =
|
|
|
|
- CryptoProtocolVersion.ENCRYPTION_ZONES;
|
|
|
|
- final XAttr ezXAttr = dir.createEncryptionZone(src, suite,
|
|
|
|
- version, keyName);
|
|
|
|
- List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
|
|
|
|
- xAttrs.add(ezXAttr);
|
|
|
|
- getEditLog().logSetXAttrs(src, xAttrs, logRetryCache);
|
|
|
|
- final INodesInPath iip = dir.getINodesInPath4Write(src, false);
|
|
|
|
- resultingStat = dir.getAuditFileInfo(iip);
|
|
|
|
- } finally {
|
|
|
|
- writeUnlock();
|
|
|
|
- }
|
|
|
|
- getEditLog().logSync();
|
|
|
|
- logAuditEvent(true, "createEncryptionZone", srcArg, null, resultingStat);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Get the encryption zone for the specified path.
|
|
* Get the encryption zone for the specified path.
|
|
*
|
|
*
|
|
@@ -7051,25 +6987,18 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
*/
|
|
*/
|
|
EncryptionZone getEZForPath(final String srcArg)
|
|
EncryptionZone getEZForPath(final String srcArg)
|
|
throws AccessControlException, UnresolvedLinkException, IOException {
|
|
throws AccessControlException, UnresolvedLinkException, IOException {
|
|
- String src = srcArg;
|
|
|
|
HdfsFileStatus resultingStat = null;
|
|
HdfsFileStatus resultingStat = null;
|
|
- final byte[][] pathComponents =
|
|
|
|
- FSDirectory.getPathComponentsForReservedPath(src);
|
|
|
|
boolean success = false;
|
|
boolean success = false;
|
|
final FSPermissionChecker pc = getPermissionChecker();
|
|
final FSPermissionChecker pc = getPermissionChecker();
|
|
checkOperation(OperationCategory.READ);
|
|
checkOperation(OperationCategory.READ);
|
|
readLock();
|
|
readLock();
|
|
try {
|
|
try {
|
|
checkOperation(OperationCategory.READ);
|
|
checkOperation(OperationCategory.READ);
|
|
- src = dir.resolvePath(pc, src, pathComponents);
|
|
|
|
- final INodesInPath iip = dir.getINodesInPath(src, true);
|
|
|
|
- if (isPermissionEnabled) {
|
|
|
|
- dir.checkPathAccess(pc, iip, FsAction.READ);
|
|
|
|
- }
|
|
|
|
- final EncryptionZone ret = dir.getEZForPath(iip);
|
|
|
|
- resultingStat = dir.getAuditFileInfo(iip);
|
|
|
|
|
|
+ Entry<EncryptionZone, HdfsFileStatus> ezForPath = FSDirEncryptionZoneOp
|
|
|
|
+ .getEZForPath(dir, srcArg, pc);
|
|
success = true;
|
|
success = true;
|
|
- return ret;
|
|
|
|
|
|
+ resultingStat = ezForPath.getValue();
|
|
|
|
+ return ezForPath.getKey();
|
|
} finally {
|
|
} finally {
|
|
readUnlock();
|
|
readUnlock();
|
|
logAuditEvent(success, "getEZForPath", srcArg, null, resultingStat);
|
|
logAuditEvent(success, "getEZForPath", srcArg, null, resultingStat);
|
|
@@ -7086,7 +7015,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
checkSuperuserPrivilege();
|
|
checkSuperuserPrivilege();
|
|
checkOperation(OperationCategory.READ);
|
|
checkOperation(OperationCategory.READ);
|
|
final BatchedListEntries<EncryptionZone> ret =
|
|
final BatchedListEntries<EncryptionZone> ret =
|
|
- dir.listEncryptionZones(prevId);
|
|
|
|
|
|
+ FSDirEncryptionZoneOp.listEncryptionZones(dir, prevId);
|
|
success = true;
|
|
success = true;
|
|
return ret;
|
|
return ret;
|
|
} finally {
|
|
} finally {
|