diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutputSaslHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutputSaslHelper.java index af2ccf9..2261086 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutputSaslHelper.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/asyncfs/FanOutOneBlockAsyncDFSOutputSaslHelper.java @@ -80,6 +80,7 @@ import org.apache.hadoop.crypto.CipherSuite; import org.apache.hadoop.crypto.CryptoCodec; import org.apache.hadoop.crypto.Decryptor; import org.apache.hadoop.crypto.Encryptor; +import org.apache.hadoop.crypto.key.KeyProvider; import org.apache.hadoop.crypto.key.KeyProvider.KeyVersion; import org.apache.hadoop.fs.FileEncryptionInfo; import org.apache.yetus.audience.InterfaceAudience; @@ -147,7 +148,7 @@ public final class FanOutOneBlockAsyncDFSOutputSaslHelper { throws IOException; } - private static final TransparentCryptoHelper TRANSPARENT_CRYPTO_HELPER; + private static volatile TransparentCryptoHelper TRANSPARENT_CRYPTO_HELPER; private static SaslAdaptor createSaslAdaptor() throws NoSuchFieldException, NoSuchMethodException { @@ -226,19 +227,41 @@ public final class FanOutOneBlockAsyncDFSOutputSaslHelper { }; } - private static TransparentCryptoHelper createTransparentCryptoHelper() - throws NoSuchMethodException { - Method decryptEncryptedDataEncryptionKeyMethod = DFSClient.class - .getDeclaredMethod("decryptEncryptedDataEncryptionKey", FileEncryptionInfo.class); - decryptEncryptedDataEncryptionKeyMethod.setAccessible(true); + private static TransparentCryptoHelper createTransparentCryptoHelper(DFSClient client) + throws IOException { + Method m1 = null; + try { + m1 = DFSClient.class + .getDeclaredMethod("decryptEncryptedDataEncryptionKey", FileEncryptionInfo.class); + m1.setAccessible(true); + } catch (NoSuchMethodException nsme) { + } + final Method decryptEncryptedDataEncryptionKeyMethod1 = m1; + Method m2 = null; + if (m1 == null) { + // post HDFS-12574, method decryptEncryptedDataEncryptionKey resides in HdfsKMSUtil + try { + Class hdfsKMSUtilCls = Class.forName("org.apache.hadoop.hdfs.HdfsKMSUtil"); + m2 = hdfsKMSUtilCls.getDeclaredMethod("decryptEncryptedDataEncryptionKey", + FileEncryptionInfo.class, KeyProvider.class); + m2.setAccessible(true); + } catch (ClassNotFoundException cnfe) { + throw new IOException(cnfe); + } catch (NoSuchMethodException nsme) { + throw new IOException(nsme); + } + } + final Method decryptEncryptedDataEncryptionKeyMethodWithKeyProvider = m2; return new TransparentCryptoHelper() { @Override public Encryptor createEncryptor(Configuration conf, FileEncryptionInfo feInfo, DFSClient client) throws IOException { try { - KeyVersion decryptedKey = - (KeyVersion) decryptEncryptedDataEncryptionKeyMethod.invoke(client, feInfo); + KeyVersion decryptedKey = decryptEncryptedDataEncryptionKeyMethod1 != null ? + (KeyVersion) decryptEncryptedDataEncryptionKeyMethod1.invoke(client, feInfo) : + (KeyVersion) decryptEncryptedDataEncryptionKeyMethodWithKeyProvider + .invoke(null, feInfo, client.getKeyProvider()) ; CryptoCodec cryptoCodec = CryptoCodec.getInstance(conf, feInfo.getCipherSuite()); Encryptor encryptor = cryptoCodec.createEncryptor(); encryptor.init(decryptedKey.getMaterial(), feInfo.getIV()); @@ -259,7 +282,7 @@ public final class FanOutOneBlockAsyncDFSOutputSaslHelper { try { SASL_ADAPTOR = createSaslAdaptor(); PB_HELPER = createPBHelper(); - TRANSPARENT_CRYPTO_HELPER = createTransparentCryptoHelper(); + TRANSPARENT_CRYPTO_HELPER = null; } catch (Exception e) { String msg = "Couldn't properly initialize access to HDFS internals. Please " + "update your WAL Provider to not make use of the 'asyncfs' provider. See " @@ -775,6 +798,9 @@ public final class FanOutOneBlockAsyncDFSOutputSaslHelper { if (feInfo == null) { return null; } + if (TRANSPARENT_CRYPTO_HELPER == null) { + TRANSPARENT_CRYPTO_HELPER = createTransparentCryptoHelper(client); + } return TRANSPARENT_CRYPTO_HELPER.createEncryptor(conf, feInfo, client); } }