/** * Constructor * @param length the number of bytes the file has * @param isdir if the path is a directory * @param block_replication the replication factor * @param blocksize the block size * @param modification_time modification time * @param access_time access time * @param permission permission * @param owner the owner of the path * @param group the group of the path * @param path the local name in java UTF8 encoding the same as that in-memory * @param fileId the file id * @param feInfo the file's encryption info */ public HdfsFileStatus(long length, boolean isdir, int block_replication, long blocksize, long modification_time, long access_time, FsPermission permission, String owner, String group, byte[] symlink, byte[] path, long fileId, int childrenNum, FileEncryptionInfo feInfo, byte storagePolicy) { this.length = length; this.isdir = isdir; this.block_replication = (short)block_replication; this.blocksize = blocksize; this.modification_time = modification_time; this.access_time = access_time; this.permission = (permission == null) ? ((isdir || symlink!=null) ? FsPermission.getDefault() : FsPermission.getFileDefault()) : permission; this.owner = (owner == null) ? "" : owner; this.group = (group == null) ? "" : group; this.symlink = symlink; this.path = path; this.fileId = fileId; this.childrenNum = childrenNum; this.feInfo = feInfo; this.storagePolicy = storagePolicy; }
/** * Decrypts a EDEK by consulting the KeyProvider. */ private KeyVersion decryptEncryptedDataEncryptionKey(FileEncryptionInfo feInfo) throws IOException { TraceScope scope = Trace.startSpan("decryptEDEK", traceSampler); try { KeyProvider provider = getKeyProvider(); if (provider == null) { throw new IOException("No KeyProvider is configured, cannot access" + " an encrypted file"); } EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption( feInfo.getKeyName(), feInfo.getEzKeyVersionName(), feInfo.getIV(), feInfo.getEncryptedDataEncryptionKey()); try { KeyProviderCryptoExtension cryptoProvider = KeyProviderCryptoExtension .createKeyProviderCryptoExtension(provider); return cryptoProvider.decryptEncryptedKey(ekv); } catch (GeneralSecurityException e) { throw new IOException(e); } } finally { scope.close(); } }
/** * Obtain a CryptoCodec based on the CipherSuite set in a FileEncryptionInfo * and the available CryptoCodecs configured in the Configuration. * * @param conf Configuration * @param feInfo FileEncryptionInfo * @return CryptoCodec * @throws IOException if no suitable CryptoCodec for the CipherSuite is * available. */ private static CryptoCodec getCryptoCodec(Configuration conf, FileEncryptionInfo feInfo) throws IOException { final CipherSuite suite = feInfo.getCipherSuite(); if (suite.equals(CipherSuite.UNKNOWN)) { throw new IOException("NameNode specified unknown CipherSuite with ID " + suite.getUnknownValue() + ", cannot instantiate CryptoCodec."); } final CryptoCodec codec = CryptoCodec.getInstance(conf, suite); if (codec == null) { throw new UnknownCipherSuiteException( "No configuration found for the cipher suite " + suite.getConfigSuffix() + " prefixed with " + HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_KEY_PREFIX + ". Please see the example configuration " + "hadoop.security.crypto.codec.classes.EXAMPLECIPHERSUITE " + "at core-default.xml for details."); } return codec; }
/** * Wraps the stream in a CryptoInputStream if the underlying file is * encrypted. */ public HdfsDataInputStream createWrappedInputStream(DFSInputStream dfsis) throws IOException { final FileEncryptionInfo feInfo = dfsis.getFileEncryptionInfo(); if (feInfo != null) { // File is encrypted, wrap the stream in a crypto stream. // Currently only one version, so no special logic based on the version # getCryptoProtocolVersion(feInfo); final CryptoCodec codec = getCryptoCodec(conf, feInfo); final KeyVersion decrypted = decryptEncryptedDataEncryptionKey(feInfo); final CryptoInputStream cryptoIn = new CryptoInputStream(dfsis, codec, decrypted.getMaterial(), feInfo.getIV()); return new HdfsDataInputStream(cryptoIn); } else { // No FileEncryptionInfo so no encryption. return new HdfsDataInputStream(dfsis); } }
/** * Wraps the stream in a CryptoOutputStream if the underlying file is * encrypted. */ public HdfsDataOutputStream createWrappedOutputStream(DFSOutputStream dfsos, FileSystem.Statistics statistics, long startPos) throws IOException { final FileEncryptionInfo feInfo = dfsos.getFileEncryptionInfo(); if (feInfo != null) { // File is encrypted, wrap the stream in a crypto stream. // Currently only one version, so no special logic based on the version # getCryptoProtocolVersion(feInfo); final CryptoCodec codec = getCryptoCodec(conf, feInfo); KeyVersion decrypted = decryptEncryptedDataEncryptionKey(feInfo); final CryptoOutputStream cryptoOut = new CryptoOutputStream(dfsos, codec, decrypted.getMaterial(), feInfo.getIV(), startPos); return new HdfsDataOutputStream(cryptoOut, statistics, startPos); } else { // No FileEncryptionInfo present so no encryption. return new HdfsDataOutputStream(dfsos, statistics, startPos); } }
/** * Set the FileEncryptionInfo for an INode. */ void setFileEncryptionInfo(String src, FileEncryptionInfo info) throws IOException { // Make the PB for the xattr final HdfsProtos.PerFileEncryptionInfoProto proto = PBHelper.convertPerFileEncInfo(info); final byte[] protoBytes = proto.toByteArray(); final XAttr fileEncryptionAttr = XAttrHelper.buildXAttr(CRYPTO_XATTR_FILE_ENCRYPTION_INFO, protoBytes); final List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); xAttrs.add(fileEncryptionAttr); writeLock(); try { FSDirXAttrOp.unprotectedSetXAttrs(this, src, xAttrs, EnumSet.of(XAttrSetFlag.CREATE)); } finally { writeUnlock(); } }
@SuppressWarnings("unchecked") private static void mockCreate(ClientProtocol mcp, CipherSuite suite, CryptoProtocolVersion version) throws Exception { Mockito.doReturn( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( (short) 777), "owner", "group", new byte[0], new byte[0], 1010, 0, new FileEncryptionInfo(suite, version, new byte[suite.getAlgorithmBlockSize()], new byte[suite.getAlgorithmBlockSize()], "fakeKey", "fakeVersion"), (byte) 0)) .when(mcp) .create(anyString(), (FsPermission) anyObject(), anyString(), (EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(), anyShort(), anyLong(), (CryptoProtocolVersion[]) anyObject()); }
/** * Decrypts a EDEK by consulting the KeyProvider. */ private KeyVersion decryptEncryptedDataEncryptionKey(FileEncryptionInfo feInfo) throws IOException { try (TraceScope ignored = tracer.newScope("decryptEDEK")) { KeyProvider provider = getKeyProvider(); if (provider == null) { throw new IOException("No KeyProvider is configured, cannot access" + " an encrypted file"); } EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption( feInfo.getKeyName(), feInfo.getEzKeyVersionName(), feInfo.getIV(), feInfo.getEncryptedDataEncryptionKey()); try { KeyProviderCryptoExtension cryptoProvider = KeyProviderCryptoExtension .createKeyProviderCryptoExtension(provider); return cryptoProvider.decryptEncryptedKey(ekv); } catch (GeneralSecurityException e) { throw new IOException(e); } } }
/** * Set the FileEncryptionInfo for an INode. * * @param fsd fsdirectory * @param src the path of a directory which will be the root of the * encryption zone. * @param info file encryption information * @throws IOException */ static void setFileEncryptionInfo(final FSDirectory fsd, final String src, final FileEncryptionInfo info) throws IOException { // Make the PB for the xattr final HdfsProtos.PerFileEncryptionInfoProto proto = PBHelperClient.convertPerFileEncInfo(info); final byte[] protoBytes = proto.toByteArray(); final XAttr fileEncryptionAttr = XAttrHelper.buildXAttr(CRYPTO_XATTR_FILE_ENCRYPTION_INFO, protoBytes); final List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); xAttrs.add(fileEncryptionAttr); fsd.writeLock(); try { FSDirXAttrOp.unprotectedSetXAttrs(fsd, src, xAttrs, EnumSet.of(XAttrSetFlag.CREATE)); } finally { fsd.writeUnlock(); } }
@SuppressWarnings("unchecked") private static void mockCreate(ClientProtocol mcp, CipherSuite suite, CryptoProtocolVersion version) throws Exception { Mockito.doReturn( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( (short) 777), "owner", "group", new byte[0], new byte[0], 1010, 0, new FileEncryptionInfo(suite, version, new byte[suite.getAlgorithmBlockSize()], new byte[suite.getAlgorithmBlockSize()], "fakeKey", "fakeVersion"), (byte) 0, null)) .when(mcp) .create(anyString(), (FsPermission) anyObject(), anyString(), (EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(), anyShort(), anyLong(), (CryptoProtocolVersion[]) anyObject()); }
/** * Decrypts a EDEK by consulting the KeyProvider. */ private KeyVersion decryptEncryptedDataEncryptionKey(FileEncryptionInfo feInfo) throws IOException { KeyProvider provider = getKeyProvider(); if (provider == null) { throw new IOException("No KeyProvider is configured, cannot access" + " an encrypted file"); } EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption( feInfo.getKeyName(), feInfo.getEzKeyVersionName(), feInfo.getIV(), feInfo.getEncryptedDataEncryptionKey()); try { KeyProviderCryptoExtension cryptoProvider = KeyProviderCryptoExtension .createKeyProviderCryptoExtension(provider); return cryptoProvider.decryptEncryptedKey(ekv); } catch (GeneralSecurityException e) { throw new IOException(e); } }
/** * Set the FileEncryptionInfo for an INode. */ void setFileEncryptionInfo(String src, FileEncryptionInfo info) throws IOException { // Make the PB for the xattr final HdfsProtos.PerFileEncryptionInfoProto proto = PBHelper.convertPerFileEncInfo(info); final byte[] protoBytes = proto.toByteArray(); final XAttr fileEncryptionAttr = XAttrHelper.buildXAttr(CRYPTO_XATTR_FILE_ENCRYPTION_INFO, protoBytes); final List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); xAttrs.add(fileEncryptionAttr); writeLock(); try { unprotectedSetXAttrs(src, xAttrs, EnumSet.of(XAttrSetFlag.CREATE)); } finally { writeUnlock(); } }
/** * Decrypts a EDEK by consulting the KeyProvider. */ private KeyVersion decryptEncryptedDataEncryptionKey(FileEncryptionInfo feInfo) throws IOException { if (provider == null) { throw new IOException("No KeyProvider is configured, cannot access" + " an encrypted file"); } EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption( feInfo.getKeyName(), feInfo.getEzKeyVersionName(), feInfo.getIV(), feInfo.getEncryptedDataEncryptionKey()); try { KeyProviderCryptoExtension cryptoProvider = KeyProviderCryptoExtension .createKeyProviderCryptoExtension(provider); return cryptoProvider.decryptEncryptedKey(ekv); } catch (GeneralSecurityException e) { throw new IOException(e); } }
public LocatedBlocks(long flength, boolean isUnderConstuction, List<LocatedBlock> blks, LocatedBlock lastBlock, boolean isLastBlockCompleted, FileEncryptionInfo feInfo) { fileLength = flength; blocks = blks; underConstruction = isUnderConstuction; this.lastLocatedBlock = lastBlock; this.isLastBlockComplete = isLastBlockCompleted; this.fileEncryptionInfo = feInfo; }
/** * Obtain the crypto protocol version from the provided FileEncryptionInfo, * checking to see if this version is supported by. * * @param feInfo FileEncryptionInfo * @return CryptoProtocolVersion from the feInfo * @throws IOException if the protocol version is unsupported. */ private static CryptoProtocolVersion getCryptoProtocolVersion (FileEncryptionInfo feInfo) throws IOException { final CryptoProtocolVersion version = feInfo.getCryptoProtocolVersion(); if (!CryptoProtocolVersion.supports(version)) { throw new IOException("Client does not support specified " + "CryptoProtocolVersion " + version.getDescription() + " version " + "number" + version.getVersion()); } return version; }
/** Create a LocatedBlocks. */ public LocatedBlocks createLocatedBlocks(final BlockInfoContiguous[] blocks, final long fileSizeExcludeBlocksUnderConstruction, final boolean isFileUnderConstruction, final long offset, final long length, final boolean needBlockToken, final boolean inSnapshot, FileEncryptionInfo feInfo) throws IOException { assert namesystem.hasReadLock(); if (blocks == null) { return null; } else if (blocks.length == 0) { return new LocatedBlocks(0, isFileUnderConstruction, Collections.<LocatedBlock>emptyList(), null, false, feInfo); } else { if (LOG.isDebugEnabled()) { LOG.debug("blocks = " + java.util.Arrays.asList(blocks)); } final AccessMode mode = needBlockToken? AccessMode.READ: null; final List<LocatedBlock> locatedblocks = createLocatedBlockList( blocks, offset, length, Integer.MAX_VALUE, mode); final LocatedBlock lastlb; final boolean isComplete; if (!inSnapshot) { final BlockInfoContiguous last = blocks[blocks.length - 1]; final long lastPos = last.isComplete()? fileSizeExcludeBlocksUnderConstruction - last.getNumBytes() : fileSizeExcludeBlocksUnderConstruction; lastlb = createLocatedBlock(last, lastPos, mode); isComplete = last.isComplete(); } else { lastlb = createLocatedBlock(blocks, fileSizeExcludeBlocksUnderConstruction, mode); isComplete = true; } return new LocatedBlocks( fileSizeExcludeBlocksUnderConstruction, isFileUnderConstruction, locatedblocks, lastlb, isComplete, feInfo); } }
public static HdfsProtos.FileEncryptionInfoProto convert( FileEncryptionInfo info) { if (info == null) { return null; } return HdfsProtos.FileEncryptionInfoProto.newBuilder() .setSuite(convert(info.getCipherSuite())) .setCryptoProtocolVersion(convert(info.getCryptoProtocolVersion())) .setKey(getByteString(info.getEncryptedDataEncryptionKey())) .setIv(getByteString(info.getIV())) .setEzKeyVersionName(info.getEzKeyVersionName()) .setKeyName(info.getKeyName()) .build(); }
public static HdfsProtos.PerFileEncryptionInfoProto convertPerFileEncInfo( FileEncryptionInfo info) { if (info == null) { return null; } return HdfsProtos.PerFileEncryptionInfoProto.newBuilder() .setKey(getByteString(info.getEncryptedDataEncryptionKey())) .setIv(getByteString(info.getIV())) .setEzKeyVersionName(info.getEzKeyVersionName()) .build(); }
public static FileEncryptionInfo convert( HdfsProtos.FileEncryptionInfoProto proto) { if (proto == null) { return null; } CipherSuite suite = convert(proto.getSuite()); CryptoProtocolVersion version = convert(proto.getCryptoProtocolVersion()); byte[] key = proto.getKey().toByteArray(); byte[] iv = proto.getIv().toByteArray(); String ezKeyVersionName = proto.getEzKeyVersionName(); String keyName = proto.getKeyName(); return new FileEncryptionInfo(suite, version, key, iv, keyName, ezKeyVersionName); }