1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.io.crypto;
18
19 import java.io.BufferedInputStream;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.InputStream;
23 import java.io.IOException;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.net.URLDecoder;
27 import java.security.Key;
28 import java.security.KeyStore;
29 import java.security.KeyStoreException;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.UnrecoverableKeyException;
32 import java.security.cert.CertificateException;
33 import java.util.Properties;
34
35 import org.apache.hadoop.hbase.classification.InterfaceAudience;
36 import org.apache.hadoop.hbase.classification.InterfaceStability;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @InterfaceAudience.Public
73 @InterfaceStability.Evolving
74 public class KeyStoreKeyProvider implements KeyProvider {
75
76 protected KeyStore store;
77 protected char[] password;
78 protected Properties passwordFile;
79
80 protected void processParameter(String name, String value) throws IOException {
81 if (name.equalsIgnoreCase(KeyProvider.PASSWORD)) {
82 password = value.toCharArray();
83 }
84 if (name.equalsIgnoreCase(KeyProvider.PASSWORDFILE)) {
85 Properties p = new Properties();
86 InputStream in = new BufferedInputStream(new FileInputStream(new File(value)));
87 try {
88 p.load(in);
89 passwordFile = p;
90 } finally {
91 in.close();
92 }
93 }
94 }
95
96 protected void processParameters(URI uri) throws IOException {
97 String params = uri.getQuery();
98 if (params == null || params.isEmpty()) {
99 return;
100 }
101 do {
102 int nameStart = 0;
103 int nameEnd = params.indexOf('=');
104 if (nameEnd == -1) {
105 throw new RuntimeException("Invalid parameters: '" + params + "'");
106 }
107 int valueStart = nameEnd + 1;
108 int valueEnd = params.indexOf('&');
109 if (valueEnd == -1) {
110 valueEnd = params.length();
111 }
112 String name = URLDecoder.decode(params.substring(nameStart, nameEnd), "UTF-8");
113 String value = URLDecoder.decode(params.substring(valueStart, valueEnd), "UTF-8");
114 processParameter(name, value);
115 params = params.substring(valueEnd, params.length());
116 } while (!params.isEmpty());
117 }
118
119 protected void load(URI uri) throws IOException {
120 String path = uri.getPath();
121 if (path == null || path.isEmpty()) {
122 throw new RuntimeException("KeyProvider parameters should specify a path");
123 }
124 InputStream is = new FileInputStream(new File(path));
125 try {
126 store.load(is, password);
127 } catch (NoSuchAlgorithmException e) {
128 throw new RuntimeException(e);
129 } catch (CertificateException e) {
130 throw new RuntimeException(e);
131 } finally {
132 is.close();
133 }
134 }
135
136 @Override
137 public void init(String params) {
138 try {
139 URI uri = new URI(params);
140 String storeType = uri.getScheme();
141 if (storeType == null || storeType.isEmpty()) {
142 throw new RuntimeException("KeyProvider scheme should specify KeyStore type");
143 }
144
145 store = KeyStore.getInstance(storeType.toUpperCase());
146 processParameters(uri);
147 load(uri);
148 } catch (URISyntaxException e) {
149 throw new RuntimeException(e);
150 } catch (KeyStoreException e) {
151 throw new RuntimeException(e);
152 } catch (IOException e) {
153 throw new RuntimeException(e);
154 }
155 }
156
157 protected char[] getAliasPassword(String alias) {
158 if (password != null) {
159 return password;
160 }
161 if (passwordFile != null) {
162 String p = passwordFile.getProperty(alias);
163 if (p != null) {
164 return p.toCharArray();
165 }
166 }
167 return null;
168 }
169
170 @Override
171 public Key getKey(String alias) {
172 try {
173 return store.getKey(alias, getAliasPassword(alias));
174 } catch (UnrecoverableKeyException e) {
175 throw new RuntimeException(e);
176 } catch (KeyStoreException e) {
177 throw new RuntimeException(e);
178 } catch (NoSuchAlgorithmException e) {
179 throw new RuntimeException(e);
180 }
181 }
182
183 @Override
184 public Key[] getKeys(String[] aliases) {
185 Key[] result = new Key[aliases.length];
186 for (int i = 0; i < aliases.length; i++) {
187 result[i] = getKey(aliases[i]);
188 }
189 return result;
190 }
191
192 }