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