1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import java.io.IOException;
22 import java.net.InetAddress;
23 import java.util.Collection;
24 import java.util.Map;
25
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
28 import org.apache.hadoop.hbase.TableName;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.hbase.ipc.RpcServer;
32 import org.apache.hadoop.hbase.security.AccessDeniedException;
33 import org.apache.hadoop.hbase.security.User;
34 import org.apache.hadoop.hbase.security.access.Permission.Action;
35 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
40 @InterfaceStability.Evolving
41 public final class AccessChecker {
42 private static final Logger AUDITLOG =
43 LoggerFactory.getLogger("SecurityLogger." + AccessChecker.class.getName());
44 private TableAuthManager authManager;
45
46
47
48
49 private boolean authorizationEnabled;
50
51 public static boolean isAuthorizationSupported(Configuration conf) {
52
53
54 return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
55 }
56
57
58
59
60
61
62
63 public AccessChecker(final Configuration conf, final ZooKeeperWatcher zkw)
64 throws RuntimeException {
65
66
67 if (zkw != null) {
68 try {
69 this.authManager = TableAuthManager.getOrCreate(zkw, conf);
70 } catch (IOException ioe) {
71 throw new RuntimeException("Error obtaining AccessChecker", ioe);
72 }
73 } else {
74 throw new NullPointerException("Error obtaining AccessChecker, zk found null.");
75 }
76 authorizationEnabled = isAuthorizationSupported(conf);
77 }
78
79 public TableAuthManager getAuthManager() {
80 return authManager;
81 }
82
83 public void logResult(AuthResult result) {
84 if (AUDITLOG.isTraceEnabled()) {
85 InetAddress remoteAddr = RpcServer.getRemoteAddress();
86 AUDITLOG.trace("Access " + (result.isAllowed() ? "allowed" : "denied") +
87 " for user " + (result.getUser() != null ? result.getUser().getShortName() : "UNKNOWN") +
88 "; reason: " + result.getReason() +
89 "; remote address: " + (remoteAddr != null ? remoteAddr : "") +
90 "; request: " + result.getRequest() +
91 "; context: " + result.toContextString());
92 }
93 }
94
95
96
97
98
99
100
101
102
103
104 public void requirePermission(User user, String request, TableName tableName, byte[] family,
105 byte[] qualifier, Action... permissions) throws IOException {
106 AuthResult result = null;
107
108 for (Action permission : permissions) {
109 if (authManager.authorize(user, tableName, family, qualifier, permission)) {
110 result = AuthResult.allow(request, "Table permission granted", user,
111 permission, tableName, family, qualifier);
112 break;
113 } else {
114
115 result = AuthResult.deny(request, "Insufficient permissions", user,
116 permission, tableName, family, qualifier);
117 }
118 }
119 logResult(result);
120 if (authorizationEnabled && !result.isAllowed()) {
121 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134 public void requireTablePermission(User user, String request, TableName tableName, byte[] family,
135 byte[] qualifier, Action... permissions) throws IOException {
136 AuthResult result = null;
137
138 for (Action permission : permissions) {
139 if (authManager.authorize(user, tableName, null, null, permission)) {
140 result = AuthResult.allow(request, "Table permission granted", user,
141 permission, tableName, null, null);
142 result.getParams().setFamily(family).setQualifier(qualifier);
143 break;
144 } else {
145
146 result = AuthResult.deny(request, "Insufficient permissions", user,
147 permission, tableName, family, qualifier);
148 result.getParams().setFamily(family).setQualifier(qualifier);
149 }
150 }
151 logResult(result);
152 if (authorizationEnabled && !result.isAllowed()) {
153 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
154 }
155 }
156
157
158
159
160
161
162
163
164
165 public void requireAccess(User user, String request, TableName tableName,
166 Action... permissions) throws IOException {
167 AuthResult result = null;
168
169 for (Action permission : permissions) {
170 if (authManager.hasAccess(user, tableName, permission)) {
171 result = AuthResult.allow(request, "Table permission granted", user,
172 permission, tableName, null, null);
173 break;
174 } else {
175
176 result = AuthResult.deny(request, "Insufficient permissions", user,
177 permission, tableName, null, null);
178 }
179 }
180 logResult(result);
181 if (authorizationEnabled && !result.isAllowed()) {
182 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
183 }
184 }
185
186
187
188
189
190
191
192 public void requirePermission(User user, String request, Action perm) throws IOException {
193 requireGlobalPermission(user, request, perm, null, null);
194 }
195
196
197
198
199
200
201
202
203
204 public void requireGlobalPermission(User user, String request, Action perm, TableName tableName,
205 Map<byte[], ? extends Collection<byte[]>> familyMap) throws IOException {
206 AuthResult result = null;
207 if (authManager.authorize(user, perm)) {
208 result = AuthResult.allow(request, "Global check allowed", user, perm, tableName, familyMap);
209 result.getParams().setTableName(tableName).setFamilies(familyMap);
210 logResult(result);
211 } else {
212 result = AuthResult.deny(request, "Global check failed", user, perm, tableName, familyMap);
213 result.getParams().setTableName(tableName).setFamilies(familyMap);
214 logResult(result);
215 if (authorizationEnabled) {
216 throw new AccessDeniedException("Insufficient permissions for user '" +
217 (user != null ? user.getShortName() : "null") +"' (global, action=" +
218 perm.toString() + ")");
219 }
220 }
221 }
222
223
224
225
226
227
228
229
230 public void requireGlobalPermission(User user, String request, Action perm,
231 String namespace) throws IOException {
232 AuthResult authResult = null;
233 if (authManager.authorize(user, perm)) {
234 authResult = AuthResult.allow(request, "Global check allowed", user, perm, null);
235 authResult.getParams().setNamespace(namespace);
236 logResult(authResult);
237 } else {
238 authResult = AuthResult.deny(request, "Global check failed", user, perm, null);
239 authResult.getParams().setNamespace(namespace);
240 logResult(authResult);
241 if (authorizationEnabled) {
242 throw new AccessDeniedException("Insufficient permissions for user '" +
243 (user != null ? user.getShortName() : "null") +"' (global, action=" +
244 perm.toString() + ")");
245 }
246 }
247 }
248
249
250
251
252
253
254 public void requireNamespacePermission(User user, String request, String namespace,
255 Action... permissions) throws IOException {
256 AuthResult result = null;
257
258 for (Action permission : permissions) {
259 if (authManager.authorize(user, namespace, permission)) {
260 result = AuthResult.allow(request, "Namespace permission granted",
261 user, permission, namespace);
262 break;
263 } else {
264
265 result = AuthResult.deny(request, "Insufficient permissions", user,
266 permission, namespace);
267 }
268 }
269 logResult(result);
270 if (authorizationEnabled && !result.isAllowed()) {
271 throw new AccessDeniedException("Insufficient permissions "
272 + result.toContextString());
273 }
274 }
275
276
277
278
279
280
281 public void requireNamespacePermission(User user, String request, String namespace,
282 TableName tableName,
283 Map<byte[], ? extends Collection<byte[]>> familyMap, Action... permissions)
284 throws IOException {
285 AuthResult result = null;
286
287 for (Action permission : permissions) {
288 if (authManager.authorize(user, namespace, permission)) {
289 result = AuthResult.allow(request, "Namespace permission granted",
290 user, permission, namespace);
291 result.getParams().setTableName(tableName).setFamilies(familyMap);
292 break;
293 } else {
294
295 result = AuthResult.deny(request, "Insufficient permissions", user,
296 permission, namespace);
297 result.getParams().setTableName(tableName).setFamilies(familyMap);
298 }
299 }
300 logResult(result);
301 if (authorizationEnabled && !result.isAllowed()) {
302 throw new AccessDeniedException("Insufficient permissions "
303 + result.toContextString());
304 }
305 }
306 }