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.KeyException;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.fs.FSDataInputStream;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.io.crypto.Cipher;
32 import org.apache.hadoop.hbase.io.crypto.Decryptor;
33 import org.apache.hadoop.hbase.io.crypto.Encryption;
34 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.WALHeader;
35 import org.apache.hadoop.hbase.regionserver.wal.ProtobufLogReader.WALHdrResult;
36 import org.apache.hadoop.hbase.security.EncryptionUtil;
37 import org.apache.hadoop.hbase.security.User;
38
39 public class SecureProtobufLogReader extends ProtobufLogReader {
40
41 private static final Log LOG = LogFactory.getLog(SecureProtobufLogReader.class);
42
43 private Decryptor decryptor = null;
44 private static List<String> writerClsNames = new ArrayList<String>();
45 static {
46 writerClsNames.add(ProtobufLogWriter.class.getSimpleName());
47 writerClsNames.add(SecureProtobufLogWriter.class.getSimpleName());
48 }
49
50 @Override
51 protected List<String> getWriterClsNames() {
52 return writerClsNames;
53 }
54
55 @Override
56 protected WALHdrContext readHeader(WALHeader.Builder builder, FSDataInputStream stream)
57 throws IOException {
58 WALHdrContext hdrCtxt = super.readHeader(builder, stream);
59 WALHdrResult result = hdrCtxt.getResult();
60
61
62
63 if (result == WALHdrResult.SUCCESS && builder.hasEncryptionKey()) {
64
65
66
67
68
69 byte[] keyBytes = builder.getEncryptionKey().toByteArray();
70 Key key = null;
71 String walKeyName = conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY);
72
73 if (walKeyName != null) {
74 try {
75 key = EncryptionUtil.unwrapKey(conf, walKeyName, keyBytes);
76 } catch (KeyException e) {
77 if (LOG.isDebugEnabled()) {
78 LOG.debug("Unable to unwrap key with WAL key '" + walKeyName + "'");
79 }
80 key = null;
81 }
82 }
83 if (key == null) {
84 String masterKeyName = conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY,
85 User.getCurrent().getShortName());
86 try {
87
88 key = EncryptionUtil.unwrapKey(conf, masterKeyName, keyBytes);
89 } catch (KeyException e) {
90
91
92 if (LOG.isDebugEnabled()) {
93 LOG.debug("Unable to unwrap key with current master key '" + masterKeyName + "'");
94 }
95 String alternateKeyName =
96 conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY);
97 if (alternateKeyName != null) {
98 try {
99 key = EncryptionUtil.unwrapKey(conf, alternateKeyName, keyBytes);
100 } catch (KeyException ex) {
101 throw new IOException(ex);
102 }
103 } else {
104 throw new IOException(e);
105 }
106 }
107 }
108
109
110
111 Cipher cipher = Encryption.getCipher(conf, key.getAlgorithm());
112 if (cipher == null) {
113 throw new IOException("Cipher '" + key.getAlgorithm() + "' is not available");
114 }
115
116
117
118 decryptor = cipher.getDecryptor();
119 decryptor.setKey(key);
120
121 if (LOG.isTraceEnabled()) {
122 LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName());
123 }
124 }
125
126 return hdrCtxt;
127 }
128
129 @Override
130 protected void initAfterCompression(String cellCodecClsName) throws IOException {
131 if (decryptor != null && cellCodecClsName.equals(SecureWALCellCodec.class.getName())) {
132 WALCellCodec codec = SecureWALCellCodec.getCodec(this.conf, decryptor);
133 this.cellDecoder = codec.getDecoder(this.inputStream);
134
135 this.compressionContext = null;
136 this.hasCompression = false;
137 } else {
138 super.initAfterCompression(cellCodecClsName);
139 }
140 }
141
142 }