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.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.io.crypto.Cipher;
35 import org.apache.hadoop.hbase.io.crypto.Encryption;
36 import org.apache.hadoop.hbase.io.crypto.Encryptor;
37 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.WALHeader;
38 import org.apache.hadoop.hbase.security.EncryptionUtil;
39 import org.apache.hadoop.hbase.security.User;
40
41 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
42 public class SecureProtobufLogWriter extends ProtobufLogWriter {
43
44 private static final Log LOG = LogFactory.getLog(SecureProtobufLogWriter.class);
45 private static final String DEFAULT_CIPHER = "AES";
46
47 private Encryptor encryptor = null;
48
49 @Override
50 protected WALHeader buildWALHeader(Configuration conf, WALHeader.Builder builder)
51 throws IOException {
52 builder.setWriterClsName(SecureProtobufLogWriter.class.getSimpleName());
53 if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) {
54
55 Cipher cipher = Encryption.getCipher(conf,
56 conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, DEFAULT_CIPHER));
57 if (cipher == null) {
58 throw new RuntimeException("Cipher '" + cipher + "' is not available");
59 }
60
61
62 SecureRandom rng = new SecureRandom();
63 byte[] keyBytes = new byte[cipher.getKeyLength()];
64 rng.nextBytes(keyBytes);
65 Key key = new SecretKeySpec(keyBytes, cipher.getName());
66 builder.setEncryptionKey(ByteStringer.wrap(EncryptionUtil.wrapKey(conf,
67 conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY,
68 conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY,
69 User.getCurrent().getShortName())),
70 key)));
71
72
73 encryptor = cipher.getEncryptor();
74 encryptor.setKey(key);
75
76 if (LOG.isTraceEnabled()) {
77 LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName());
78 }
79 }
80 builder.setCellCodecClsName(SecureWALCellCodec.class.getName());
81 return super.buildWALHeader(conf, builder);
82 }
83
84 @Override
85 protected void initAfterHeader(boolean doCompress) throws IOException {
86 if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false) && encryptor != null) {
87 WALCellCodec codec = SecureWALCellCodec.getCodec(this.conf, encryptor);
88 this.cellEncoder = codec.getEncoder(this.output);
89
90 this.compressionContext = null;
91 } else {
92 super.initAfterHeader(doCompress);
93 }
94 }
95
96 }