1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.regionserver.wal;
20
21 import java.io.IOException;
22 import java.security.Key;
23 import java.security.SecureRandom;
24
25 import javax.crypto.spec.SecretKeySpec;
26
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.util.ByteStringer;
29 import org.apache.hadoop.hbase.util.EncryptionTest;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.io.crypto.Cipher;
36 import org.apache.hadoop.hbase.io.crypto.Encryption;
37 import org.apache.hadoop.hbase.io.crypto.Encryptor;
38 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.WALHeader;
39 import org.apache.hadoop.hbase.security.EncryptionUtil;
40 import org.apache.hadoop.hbase.security.User;
41
42 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
43 public class SecureProtobufLogWriter extends ProtobufLogWriter {
44
45 private static final Log LOG = LogFactory.getLog(SecureProtobufLogWriter.class);
46 private Encryptor encryptor = null;
47
48 @Override
49 protected WALHeader buildWALHeader(Configuration conf, WALHeader.Builder builder)
50 throws IOException {
51 builder.setWriterClsName(SecureProtobufLogWriter.class.getSimpleName());
52 if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) {
53 EncryptionTest.testKeyProvider(conf);
54 EncryptionTest.testCipherProvider(conf);
55
56
57 final String cipherName =
58 conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES);
59 Cipher cipher = Encryption.getCipher(conf, cipherName);
60 if (cipher == null) {
61 throw new RuntimeException("Cipher '" + cipherName + "' is not available");
62 }
63
64
65 SecureRandom rng = new SecureRandom();
66 byte[] keyBytes = new byte[cipher.getKeyLength()];
67 rng.nextBytes(keyBytes);
68 Key key = new SecretKeySpec(keyBytes, cipher.getName());
69 builder.setEncryptionKey(ByteStringer.wrap(EncryptionUtil.wrapKey(conf,
70 conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY,
71 conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY,
72 User.getCurrent().getShortName())),
73 key)));
74
75
76 encryptor = cipher.getEncryptor();
77 encryptor.setKey(key);
78
79 if (LOG.isTraceEnabled()) {
80 LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName());
81 }
82 }
83 builder.setCellCodecClsName(SecureWALCellCodec.class.getName());
84 return super.buildWALHeader(conf, builder);
85 }
86
87 @Override
88 protected void initAfterHeader(boolean doCompress) throws IOException {
89 if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false) && encryptor != null) {
90 WALCellCodec codec = SecureWALCellCodec.getCodec(this.conf, encryptor);
91 this.cellEncoder = codec.getEncoder(this.output);
92
93 this.compressionContext = null;
94 } else {
95 super.initAfterHeader(doCompress);
96 }
97 }
98
99 }