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