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