001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security.access; 019 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.List; 023import java.util.Map; 024import java.util.Objects; 025import org.apache.commons.lang3.StringUtils; 026import org.apache.hadoop.hbase.HConstants; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.client.Admin; 029import org.apache.hadoop.hbase.util.Bytes; 030import org.apache.yetus.audience.InterfaceAudience; 031 032import org.apache.hbase.thirdparty.com.google.common.collect.ArrayListMultimap; 033import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap; 034import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 035import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 036import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; 037import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 038import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 039 040import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 041import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos; 042import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.AccessControlService; 043import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse; 044 045@InterfaceAudience.Private 046public class AccessControlUtil { 047 private AccessControlUtil() { 048 } 049 050 /** 051 * Create a request to grant user table permissions. 052 * @param username the short user name who to grant permissions 053 * @param tableName optional table name the permissions apply 054 * @param family optional column family 055 * @param qualifier optional qualifier 056 * @param actions the permissions to be granted 057 * @return A {@link AccessControlProtos} GrantRequest 058 * @throws NullPointerException if {@code tableName} is {@code null} 059 */ 060 public static AccessControlProtos.GrantRequest buildGrantRequest(String username, 061 TableName tableName, byte[] family, byte[] qualifier, boolean mergeExistingPermissions, 062 AccessControlProtos.Permission.Action... actions) { 063 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 064 AccessControlProtos.TablePermission.Builder permissionBuilder = 065 AccessControlProtos.TablePermission.newBuilder(); 066 for (AccessControlProtos.Permission.Action a : actions) { 067 permissionBuilder.addAction(a); 068 } 069 070 Objects.requireNonNull(tableName, "TableName cannot be null"); 071 072 permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName)); 073 074 if (family != null) { 075 permissionBuilder.setFamily(UnsafeByteOperations.unsafeWrap(family)); 076 } 077 if (qualifier != null) { 078 permissionBuilder.setQualifier(UnsafeByteOperations.unsafeWrap(qualifier)); 079 } 080 ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(permissionBuilder); 081 return AccessControlProtos.GrantRequest.newBuilder() 082 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 083 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 084 .setMergeExistingPermissions(mergeExistingPermissions).build(); 085 } 086 087 /** 088 * Create a request to grant user namespace permissions. 089 * @param username the short user name who to grant permissions 090 * @param namespace optional table name the permissions apply 091 * @param actions the permissions to be granted 092 * @return A {@link AccessControlProtos} GrantRequest 093 */ 094 public static AccessControlProtos.GrantRequest buildGrantRequest(String username, 095 String namespace, boolean mergeExistingPermissions, 096 AccessControlProtos.Permission.Action... actions) { 097 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 098 AccessControlProtos.NamespacePermission.Builder permissionBuilder = 099 AccessControlProtos.NamespacePermission.newBuilder(); 100 for (AccessControlProtos.Permission.Action a : actions) { 101 permissionBuilder.addAction(a); 102 } 103 if (namespace != null) { 104 permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace)); 105 } 106 ret.setType(AccessControlProtos.Permission.Type.Namespace) 107 .setNamespacePermission(permissionBuilder); 108 return AccessControlProtos.GrantRequest.newBuilder() 109 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 110 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 111 .setMergeExistingPermissions(mergeExistingPermissions).build(); 112 } 113 114 /** 115 * Create a request to revoke user global permissions. 116 * @param username the short user name whose permissions to be revoked 117 * @param actions the permissions to be revoked 118 * @return A {@link AccessControlProtos} RevokeRequest 119 */ 120 public static AccessControlProtos.RevokeRequest buildRevokeRequest(String username, 121 AccessControlProtos.Permission.Action... actions) { 122 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 123 AccessControlProtos.GlobalPermission.Builder permissionBuilder = 124 AccessControlProtos.GlobalPermission.newBuilder(); 125 for (AccessControlProtos.Permission.Action a : actions) { 126 permissionBuilder.addAction(a); 127 } 128 ret.setType(AccessControlProtos.Permission.Type.Global).setGlobalPermission(permissionBuilder); 129 return AccessControlProtos.RevokeRequest.newBuilder() 130 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 131 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 132 .build(); 133 } 134 135 /** 136 * Create a request to revoke user namespace permissions. 137 * @param username the short user name whose permissions to be revoked 138 * @param namespace optional table name the permissions apply 139 * @param actions the permissions to be revoked 140 * @return A {@link AccessControlProtos} RevokeRequest 141 */ 142 public static AccessControlProtos.RevokeRequest buildRevokeRequest(String username, 143 String namespace, AccessControlProtos.Permission.Action... actions) { 144 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 145 AccessControlProtos.NamespacePermission.Builder permissionBuilder = 146 AccessControlProtos.NamespacePermission.newBuilder(); 147 for (AccessControlProtos.Permission.Action a : actions) { 148 permissionBuilder.addAction(a); 149 } 150 if (namespace != null) { 151 permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace)); 152 } 153 ret.setType(AccessControlProtos.Permission.Type.Namespace) 154 .setNamespacePermission(permissionBuilder); 155 return AccessControlProtos.RevokeRequest.newBuilder() 156 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 157 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 158 .build(); 159 } 160 161 /** 162 * Create a request to grant user global permissions. 163 * @param username the short user name who to grant permissions 164 * @param actions the permissions to be granted 165 * @return A {@link AccessControlProtos} GrantRequest 166 */ 167 public static AccessControlProtos.GrantRequest buildGrantRequest(String username, 168 boolean mergeExistingPermissions, AccessControlProtos.Permission.Action... actions) { 169 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 170 AccessControlProtos.GlobalPermission.Builder permissionBuilder = 171 AccessControlProtos.GlobalPermission.newBuilder(); 172 for (AccessControlProtos.Permission.Action a : actions) { 173 permissionBuilder.addAction(a); 174 } 175 ret.setType(AccessControlProtos.Permission.Type.Global).setGlobalPermission(permissionBuilder); 176 return AccessControlProtos.GrantRequest.newBuilder() 177 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 178 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 179 .setMergeExistingPermissions(mergeExistingPermissions).build(); 180 } 181 182 public static AccessControlProtos.UsersAndPermissions toUsersAndPermissions(String user, 183 Permission perms) { 184 return AccessControlProtos.UsersAndPermissions.newBuilder() 185 .addUserPermissions(AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder() 186 .setUser(ByteString.copyFromUtf8(user)).addPermissions(toPermission(perms)).build()) 187 .build(); 188 } 189 190 public static AccessControlProtos.UsersAndPermissions 191 toUsersAndPermissions(ListMultimap<String, Permission> perms) { 192 AccessControlProtos.UsersAndPermissions.Builder builder = 193 AccessControlProtos.UsersAndPermissions.newBuilder(); 194 for (Map.Entry<String, Collection<Permission>> entry : perms.asMap().entrySet()) { 195 AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder = 196 AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder(); 197 userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey())); 198 for (Permission perm : entry.getValue()) { 199 userPermBuilder.addPermissions(toPermission(perm)); 200 } 201 builder.addUserPermissions(userPermBuilder.build()); 202 } 203 return builder.build(); 204 } 205 206 public static ListMultimap<String, Permission> 207 toUsersAndPermissions(AccessControlProtos.UsersAndPermissions proto) { 208 ListMultimap<String, Permission> result = ArrayListMultimap.create(); 209 for (AccessControlProtos.UsersAndPermissions.UserPermissions userPerms : proto 210 .getUserPermissionsList()) { 211 String user = userPerms.getUser().toStringUtf8(); 212 for (AccessControlProtos.Permission perm : userPerms.getPermissionsList()) { 213 result.put(user, toPermission(perm)); 214 } 215 } 216 return result; 217 } 218 219 /** 220 * Converts a TablePermission proto to a client TablePermission object. 221 * @param proto the protobuf TablePermission 222 * @return the converted TablePermission 223 */ 224 public static TablePermission toTablePermission(AccessControlProtos.TablePermission proto) { 225 Permission.Action[] actions = toPermissionActions(proto.getActionList()); 226 if (!proto.hasTableName()) { 227 throw new IllegalStateException("TableName cannot be empty"); 228 } 229 TableName table = ProtobufUtil.toTableName(proto.getTableName()); 230 byte[] family = null; 231 byte[] qualifier = null; 232 if (proto.hasFamily()) { 233 family = proto.getFamily().toByteArray(); 234 } 235 if (proto.hasQualifier()) { 236 qualifier = proto.getQualifier().toByteArray(); 237 } 238 return new TablePermission(table, family, qualifier, actions); 239 } 240 241 /** 242 * Converts a Permission proto to a client Permission object. 243 * @param proto the protobuf Permission 244 * @return the converted Permission 245 */ 246 public static Permission toPermission(AccessControlProtos.Permission proto) { 247 if (proto.getType() == AccessControlProtos.Permission.Type.Global) { 248 AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission(); 249 Permission.Action[] actions = toPermissionActions(perm.getActionList()); 250 return Permission.newBuilder().withActions(actions).build(); 251 } 252 if (proto.getType() == AccessControlProtos.Permission.Type.Namespace) { 253 AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission(); 254 Permission.Action[] actions = toPermissionActions(perm.getActionList()); 255 if (!proto.hasNamespacePermission()) { 256 throw new IllegalStateException("Namespace must not be empty in NamespacePermission"); 257 } 258 return Permission.newBuilder(perm.getNamespaceName().toStringUtf8()).withActions(actions) 259 .build(); 260 } 261 if (proto.getType() == AccessControlProtos.Permission.Type.Table) { 262 AccessControlProtos.TablePermission perm = proto.getTablePermission(); 263 Permission.Action[] actions = toPermissionActions(perm.getActionList()); 264 if (!perm.hasTableName()) { 265 throw new IllegalStateException("TableName cannot be empty"); 266 } 267 TableName table = ProtobufUtil.toTableName(perm.getTableName()); 268 byte[] family = null; 269 byte[] qualifier = null; 270 if (perm.hasFamily()) { 271 family = perm.getFamily().toByteArray(); 272 } 273 if (perm.hasQualifier()) { 274 qualifier = perm.getQualifier().toByteArray(); 275 } 276 return Permission.newBuilder(table).withFamily(family).withQualifier(qualifier) 277 .withActions(actions).build(); 278 } 279 throw new IllegalStateException("Unrecognize Perm Type: " + proto.getType()); 280 } 281 282 /** 283 * Convert a client Permission to a Permission proto 284 * @param perm the client Permission 285 * @return the protobuf Permission 286 */ 287 public static AccessControlProtos.Permission toPermission(Permission perm) { 288 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 289 if (perm instanceof NamespacePermission) { 290 NamespacePermission namespace = (NamespacePermission) perm; 291 ret.setType(AccessControlProtos.Permission.Type.Namespace); 292 AccessControlProtos.NamespacePermission.Builder builder = 293 AccessControlProtos.NamespacePermission.newBuilder(); 294 builder.setNamespaceName(ByteString.copyFromUtf8(namespace.getNamespace())); 295 Permission.Action[] actions = perm.getActions(); 296 if (actions != null) { 297 for (Permission.Action a : actions) { 298 builder.addAction(toPermissionAction(a)); 299 } 300 } 301 ret.setNamespacePermission(builder); 302 } else if (perm instanceof TablePermission) { 303 TablePermission table = (TablePermission) perm; 304 ret.setType(AccessControlProtos.Permission.Type.Table); 305 AccessControlProtos.TablePermission.Builder builder = 306 AccessControlProtos.TablePermission.newBuilder(); 307 builder.setTableName(ProtobufUtil.toProtoTableName(table.getTableName())); 308 if (table.hasFamily()) { 309 builder.setFamily(UnsafeByteOperations.unsafeWrap(table.getFamily())); 310 } 311 if (table.hasQualifier()) { 312 builder.setQualifier(UnsafeByteOperations.unsafeWrap(table.getQualifier())); 313 } 314 Permission.Action[] actions = perm.getActions(); 315 if (actions != null) { 316 for (Permission.Action a : actions) { 317 builder.addAction(toPermissionAction(a)); 318 } 319 } 320 ret.setTablePermission(builder); 321 } else { 322 // perm instanceof GlobalPermission 323 ret.setType(AccessControlProtos.Permission.Type.Global); 324 AccessControlProtos.GlobalPermission.Builder builder = 325 AccessControlProtos.GlobalPermission.newBuilder(); 326 Permission.Action[] actions = perm.getActions(); 327 if (actions != null) { 328 for (Permission.Action a : actions) { 329 builder.addAction(toPermissionAction(a)); 330 } 331 } 332 ret.setGlobalPermission(builder); 333 } 334 return ret.build(); 335 } 336 337 /** 338 * Converts a list of Permission.Action proto to an array of client Permission.Action objects. 339 * @param protoActions the list of protobuf Actions 340 * @return the converted array of Actions 341 */ 342 public static Permission.Action[] 343 toPermissionActions(List<AccessControlProtos.Permission.Action> protoActions) { 344 Permission.Action[] actions = new Permission.Action[protoActions.size()]; 345 for (int i = 0; i < protoActions.size(); i++) { 346 actions[i] = toPermissionAction(protoActions.get(i)); 347 } 348 return actions; 349 } 350 351 /** 352 * Converts a Permission.Action proto to a client Permission.Action object. 353 * @param action the protobuf Action 354 * @return the converted Action 355 */ 356 public static Permission.Action toPermissionAction(AccessControlProtos.Permission.Action action) { 357 switch (action) { 358 case READ: 359 return Permission.Action.READ; 360 case WRITE: 361 return Permission.Action.WRITE; 362 case EXEC: 363 return Permission.Action.EXEC; 364 case CREATE: 365 return Permission.Action.CREATE; 366 case ADMIN: 367 return Permission.Action.ADMIN; 368 } 369 throw new IllegalArgumentException("Unknown action value " + action.name()); 370 } 371 372 /** 373 * Convert a client Permission.Action to a Permission.Action proto 374 * @param action the client Action 375 * @return the protobuf Action 376 */ 377 public static AccessControlProtos.Permission.Action toPermissionAction(Permission.Action action) { 378 switch (action) { 379 case READ: 380 return AccessControlProtos.Permission.Action.READ; 381 case WRITE: 382 return AccessControlProtos.Permission.Action.WRITE; 383 case EXEC: 384 return AccessControlProtos.Permission.Action.EXEC; 385 case CREATE: 386 return AccessControlProtos.Permission.Action.CREATE; 387 case ADMIN: 388 return AccessControlProtos.Permission.Action.ADMIN; 389 } 390 throw new IllegalArgumentException("Unknown action value " + action.name()); 391 } 392 393 /** 394 * Convert a client user permission to a user permission proto 395 * @param perm the client UserPermission 396 * @return the protobuf UserPermission 397 */ 398 public static AccessControlProtos.UserPermission toUserPermission(UserPermission perm) { 399 return AccessControlProtos.UserPermission.newBuilder() 400 .setUser(ByteString.copyFromUtf8(perm.getUser())) 401 .setPermission(toPermission(perm.getPermission())).build(); 402 } 403 404 /** 405 * Converts the permissions list into a protocol buffer GetUserPermissionsResponse 406 */ 407 public static GetUserPermissionsResponse 408 buildGetUserPermissionsResponse(final List<UserPermission> permissions) { 409 GetUserPermissionsResponse.Builder builder = GetUserPermissionsResponse.newBuilder(); 410 for (UserPermission perm : permissions) { 411 builder.addUserPermission(toUserPermission(perm)); 412 } 413 return builder.build(); 414 } 415 416 /** 417 * Converts a user permission proto to a client user permission object. 418 * @param proto the protobuf UserPermission 419 * @return the converted UserPermission 420 */ 421 public static UserPermission toUserPermission(AccessControlProtos.UserPermission proto) { 422 return new UserPermission(proto.getUser().toStringUtf8(), toPermission(proto.getPermission())); 423 } 424 425 /** 426 * Convert a ListMultimap<String, TablePermission> where key is username to a protobuf 427 * UserPermission 428 * @param perm the list of user and table permissions 429 * @return the protobuf UserTablePermissions 430 */ 431 public static AccessControlProtos.UsersAndPermissions 432 toUserTablePermissions(ListMultimap<String, UserPermission> perm) { 433 AccessControlProtos.UsersAndPermissions.Builder builder = 434 AccessControlProtos.UsersAndPermissions.newBuilder(); 435 for (Map.Entry<String, Collection<UserPermission>> entry : perm.asMap().entrySet()) { 436 AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder = 437 AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder(); 438 userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey())); 439 for (UserPermission userPerm : entry.getValue()) { 440 userPermBuilder.addPermissions(toPermission(userPerm.getPermission())); 441 } 442 builder.addUserPermissions(userPermBuilder.build()); 443 } 444 return builder.build(); 445 } 446 447 /** 448 * A utility used to grant a user global permissions. 449 * <p> 450 * It's also called by the shell, in case you want to find references. 451 * @param protocol the AccessControlService protocol proxy 452 * @param userShortName the short name of the user to grant permissions 453 * @param actions the permissions to be granted 454 * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. 455 */ 456 @Deprecated 457 public static void grant(RpcController controller, 458 AccessControlService.BlockingInterface protocol, String userShortName, 459 boolean mergeExistingPermissions, Permission.Action... actions) throws ServiceException { 460 List<AccessControlProtos.Permission.Action> permActions = 461 Lists.newArrayListWithCapacity(actions.length); 462 for (Permission.Action a : actions) { 463 permActions.add(toPermissionAction(a)); 464 } 465 AccessControlProtos.GrantRequest request = 466 buildGrantRequest(userShortName, mergeExistingPermissions, 467 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 468 protocol.grant(controller, request); 469 } 470 471 /** 472 * A utility used to grant a user table permissions. The permissions will be for a table 473 * table/column family/qualifier. 474 * <p> 475 * It's also called by the shell, in case you want to find references. 476 * @param protocol the AccessControlService protocol proxy 477 * @param userShortName the short name of the user to grant permissions 478 * @param tableName optional table name 479 * @param f optional column family 480 * @param q optional qualifier 481 * @param actions the permissions to be granted 482 * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. 483 */ 484 @Deprecated 485 public static void grant(RpcController controller, 486 AccessControlService.BlockingInterface protocol, String userShortName, TableName tableName, 487 byte[] f, byte[] q, boolean mergeExistingPermissions, Permission.Action... actions) 488 throws ServiceException { 489 List<AccessControlProtos.Permission.Action> permActions = 490 Lists.newArrayListWithCapacity(actions.length); 491 for (Permission.Action a : actions) { 492 permActions.add(toPermissionAction(a)); 493 } 494 AccessControlProtos.GrantRequest request = 495 buildGrantRequest(userShortName, tableName, f, q, mergeExistingPermissions, 496 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 497 protocol.grant(controller, request); 498 } 499 500 /** 501 * A utility used to grant a user namespace permissions. 502 * <p> 503 * It's also called by the shell, in case you want to find references. 504 * @param controller RpcController 505 * @param protocol the AccessControlService protocol proxy 506 * @param namespace the short name of the user to grant permissions 507 * @param actions the permissions to be granted 508 * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. 509 */ 510 @Deprecated 511 public static void grant(RpcController controller, 512 AccessControlService.BlockingInterface protocol, String userShortName, String namespace, 513 boolean mergeExistingPermissions, Permission.Action... actions) throws ServiceException { 514 List<AccessControlProtos.Permission.Action> permActions = 515 Lists.newArrayListWithCapacity(actions.length); 516 for (Permission.Action a : actions) { 517 permActions.add(toPermissionAction(a)); 518 } 519 AccessControlProtos.GrantRequest request = 520 buildGrantRequest(userShortName, namespace, mergeExistingPermissions, 521 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 522 protocol.grant(controller, request); 523 } 524 525 /** 526 * A utility used to revoke a user's global permissions. 527 * <p> 528 * It's also called by the shell, in case you want to find references. 529 * @param controller RpcController 530 * @param protocol the AccessControlService protocol proxy 531 * @param userShortName the short name of the user to revoke permissions 532 * @param actions the permissions to be revoked 533 * @throws ServiceException on failure 534 * @deprecated Use {@link Admin#revoke(UserPermission)} instead. 535 */ 536 @Deprecated 537 public static void revoke(RpcController controller, 538 AccessControlService.BlockingInterface protocol, String userShortName, 539 Permission.Action... actions) throws ServiceException { 540 List<AccessControlProtos.Permission.Action> permActions = 541 Lists.newArrayListWithCapacity(actions.length); 542 for (Permission.Action a : actions) { 543 permActions.add(toPermissionAction(a)); 544 } 545 AccessControlProtos.RevokeRequest request = buildRevokeRequest(userShortName, 546 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 547 protocol.revoke(controller, request); 548 } 549 550 /** 551 * A utility used to revoke a user's table permissions. The permissions will be for a table/column 552 * family/qualifier. 553 * <p> 554 * It's also called by the shell, in case you want to find references. 555 * @param controller RpcController 556 * @param protocol the AccessControlService protocol proxy 557 * @param userShortName the short name of the user to revoke permissions 558 * @param tableName optional table name 559 * @param f optional column family 560 * @param q optional qualifier 561 * @param actions the permissions to be revoked 562 * @throws ServiceException on failure 563 * @deprecated Use {@link Admin#revoke(UserPermission)} instead. 564 */ 565 @Deprecated 566 public static void revoke(RpcController controller, 567 AccessControlService.BlockingInterface protocol, String userShortName, TableName tableName, 568 byte[] f, byte[] q, Permission.Action... actions) throws ServiceException { 569 List<AccessControlProtos.Permission.Action> permActions = 570 Lists.newArrayListWithCapacity(actions.length); 571 for (Permission.Action a : actions) { 572 permActions.add(toPermissionAction(a)); 573 } 574 AccessControlProtos.RevokeRequest request = buildRevokeRequest(userShortName, tableName, f, q, 575 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 576 protocol.revoke(controller, request); 577 } 578 579 /** 580 * A utility used to revoke a user's namespace permissions. 581 * <p> 582 * It's also called by the shell, in case you want to find references. 583 * @param controller RpcController 584 * @param protocol the AccessControlService protocol proxy 585 * @param userShortName the short name of the user to revoke permissions 586 * @param namespace optional table name 587 * @param actions the permissions to be revoked 588 * @throws ServiceException on failure 589 * @deprecated Use {@link Admin#revoke(UserPermission)} instead. 590 */ 591 @Deprecated 592 public static void revoke(RpcController controller, 593 AccessControlService.BlockingInterface protocol, String userShortName, String namespace, 594 Permission.Action... actions) throws ServiceException { 595 List<AccessControlProtos.Permission.Action> permActions = 596 Lists.newArrayListWithCapacity(actions.length); 597 for (Permission.Action a : actions) { 598 permActions.add(toPermissionAction(a)); 599 } 600 AccessControlProtos.RevokeRequest request = buildRevokeRequest(userShortName, namespace, 601 permActions.toArray(new AccessControlProtos.Permission.Action[actions.length])); 602 protocol.revoke(controller, request); 603 } 604 605 /** 606 * A utility used to get user's global permissions. 607 * <p> 608 * It's also called by the shell, in case you want to find references. 609 * @param controller RpcController 610 * @param protocol the AccessControlService protocol proxy 611 * @throws ServiceException on failure 612 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 613 */ 614 @Deprecated 615 public static List<UserPermission> getUserPermissions(RpcController controller, 616 AccessControlService.BlockingInterface protocol) throws ServiceException { 617 return getUserPermissions(controller, protocol, HConstants.EMPTY_STRING); 618 } 619 620 /** 621 * A utility used to get user's global permissions based on the specified user name. 622 * @param controller RpcController 623 * @param protocol the AccessControlService protocol proxy 624 * @param userName User name, if empty then all user permissions will be retrieved. 625 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 626 */ 627 @Deprecated 628 public static List<UserPermission> getUserPermissions(RpcController controller, 629 AccessControlService.BlockingInterface protocol, String userName) throws ServiceException { 630 AccessControlProtos.GetUserPermissionsRequest.Builder builder = 631 AccessControlProtos.GetUserPermissionsRequest.newBuilder(); 632 builder.setType(AccessControlProtos.Permission.Type.Global); 633 if (!StringUtils.isEmpty(userName)) { 634 builder.setUserName(ByteString.copyFromUtf8(userName)); 635 } 636 637 AccessControlProtos.GetUserPermissionsRequest request = builder.build(); 638 AccessControlProtos.GetUserPermissionsResponse response = 639 protocol.getUserPermissions(controller, request); 640 List<UserPermission> perms = new ArrayList<>(response.getUserPermissionCount()); 641 for (AccessControlProtos.UserPermission perm : response.getUserPermissionList()) { 642 perms.add(toUserPermission(perm)); 643 } 644 return perms; 645 } 646 647 /** 648 * A utility used to get user table permissions. 649 * <p> 650 * It's also called by the shell, in case you want to find references. 651 * @param controller RpcController 652 * @param protocol the AccessControlService protocol proxy 653 * @param t optional table name 654 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 655 */ 656 @Deprecated 657 public static List<UserPermission> getUserPermissions(RpcController controller, 658 AccessControlService.BlockingInterface protocol, TableName t) throws ServiceException { 659 return getUserPermissions(controller, protocol, t, null, null, HConstants.EMPTY_STRING); 660 } 661 662 /** 663 * A utility used to get user table permissions based on the column family, column qualifier and 664 * user name. 665 * @param controller RpcController 666 * @param protocol the AccessControlService protocol proxy 667 * @param t optional table name 668 * @param columnFamily Column family 669 * @param columnQualifier Column qualifier 670 * @param userName User name, if empty then all user permissions will be retrieved. 671 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 672 */ 673 @Deprecated 674 public static List<UserPermission> getUserPermissions(RpcController controller, 675 AccessControlService.BlockingInterface protocol, TableName t, byte[] columnFamily, 676 byte[] columnQualifier, String userName) throws ServiceException { 677 AccessControlProtos.GetUserPermissionsRequest.Builder builder = 678 AccessControlProtos.GetUserPermissionsRequest.newBuilder(); 679 if (t != null) { 680 builder.setTableName(ProtobufUtil.toProtoTableName(t)); 681 } 682 if (Bytes.len(columnFamily) > 0) { 683 builder.setColumnFamily(ByteString.copyFrom(columnFamily)); 684 } 685 if (Bytes.len(columnQualifier) > 0) { 686 builder.setColumnQualifier(ByteString.copyFrom(columnQualifier)); 687 } 688 if (!StringUtils.isEmpty(userName)) { 689 builder.setUserName(ByteString.copyFromUtf8(userName)); 690 } 691 692 builder.setType(AccessControlProtos.Permission.Type.Table); 693 AccessControlProtos.GetUserPermissionsRequest request = builder.build(); 694 AccessControlProtos.GetUserPermissionsResponse response = 695 protocol.getUserPermissions(controller, request); 696 List<UserPermission> perms = new ArrayList<>(response.getUserPermissionCount()); 697 for (AccessControlProtos.UserPermission perm : response.getUserPermissionList()) { 698 perms.add(toUserPermission(perm)); 699 } 700 return perms; 701 } 702 703 /** 704 * A utility used to get permissions for selected namespace. 705 * <p> 706 * It's also called by the shell, in case you want to find references. 707 * @param controller RpcController 708 * @param protocol the AccessControlService protocol proxy 709 * @param namespace name of the namespace 710 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 711 */ 712 @Deprecated 713 public static List<UserPermission> getUserPermissions(RpcController controller, 714 AccessControlService.BlockingInterface protocol, byte[] namespace) throws ServiceException { 715 return getUserPermissions(controller, protocol, namespace, HConstants.EMPTY_STRING); 716 } 717 718 /** 719 * A utility used to get permissions for selected namespace based on the specified user name. 720 * @param controller RpcController 721 * @param protocol the AccessControlService protocol proxy 722 * @param namespace name of the namespace 723 * @param userName User name, if empty then all user permissions will be retrieved. 724 * @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead. 725 */ 726 @Deprecated 727 public static List<UserPermission> getUserPermissions(RpcController controller, 728 AccessControlService.BlockingInterface protocol, byte[] namespace, String userName) 729 throws ServiceException { 730 AccessControlProtos.GetUserPermissionsRequest.Builder builder = 731 AccessControlProtos.GetUserPermissionsRequest.newBuilder(); 732 if (namespace != null) { 733 builder.setNamespaceName(UnsafeByteOperations.unsafeWrap(namespace)); 734 } 735 if (!StringUtils.isEmpty(userName)) { 736 builder.setUserName(ByteString.copyFromUtf8(userName)); 737 } 738 builder.setType(AccessControlProtos.Permission.Type.Namespace); 739 AccessControlProtos.GetUserPermissionsRequest request = builder.build(); 740 AccessControlProtos.GetUserPermissionsResponse response = 741 protocol.getUserPermissions(controller, request); 742 List<UserPermission> perms = new ArrayList<>(response.getUserPermissionCount()); 743 for (AccessControlProtos.UserPermission perm : response.getUserPermissionList()) { 744 perms.add(toUserPermission(perm)); 745 } 746 return perms; 747 } 748 749 /** 750 * Validates whether specified user has permission to perform actions on the mentioned table, 751 * column family or column qualifier. 752 * @param controller RpcController 753 * @param protocol the AccessControlService protocol proxy 754 * @param tableName Table name, it shouldn't be null or empty. 755 * @param columnFamily The column family. Optional argument, can be empty. If empty then 756 * validation will happen at table level. 757 * @param columnQualifier The column qualifier. Optional argument, can be empty. If empty then 758 * validation will happen at table and column family level. columnQualifier 759 * will not be considered if columnFamily is passed as null or empty. 760 * @param userName User name, it shouldn't be null or empty. 761 * @param actions Actions 762 * @return true if access allowed, otherwise false 763 * @deprecated Use {@link Admin#hasUserPermissions(String, List)} instead. 764 */ 765 @Deprecated 766 public static boolean hasPermission(RpcController controller, 767 AccessControlService.BlockingInterface protocol, TableName tableName, byte[] columnFamily, 768 byte[] columnQualifier, String userName, Permission.Action[] actions) throws ServiceException { 769 AccessControlProtos.TablePermission.Builder tablePermissionBuilder = 770 AccessControlProtos.TablePermission.newBuilder(); 771 tablePermissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName)); 772 if (Bytes.len(columnFamily) > 0) { 773 tablePermissionBuilder.setFamily(UnsafeByteOperations.unsafeWrap(columnFamily)); 774 } 775 if (Bytes.len(columnQualifier) > 0) { 776 tablePermissionBuilder.setQualifier(UnsafeByteOperations.unsafeWrap(columnQualifier)); 777 } 778 for (Permission.Action a : actions) { 779 tablePermissionBuilder.addAction(toPermissionAction(a)); 780 } 781 AccessControlProtos.HasPermissionRequest request = AccessControlProtos.HasPermissionRequest 782 .newBuilder().setTablePermission(tablePermissionBuilder) 783 .setUserName(ByteString.copyFromUtf8(userName)).build(); 784 AccessControlProtos.HasPermissionResponse response = 785 protocol.hasPermission(controller, request); 786 return response.getHasPermission(); 787 } 788 789 /** 790 * Convert a protobuf UserTablePermissions to a ListMultimap<Username, UserPermission> 791 * @param proto the proto UsersAndPermissions 792 * @return a ListMultimap with user and its permissions 793 */ 794 public static ListMultimap<String, UserPermission> 795 toUserPermission(AccessControlProtos.UsersAndPermissions proto) { 796 ListMultimap<String, UserPermission> userPermission = ArrayListMultimap.create(); 797 AccessControlProtos.UsersAndPermissions.UserPermissions userPerm; 798 for (int i = 0; i < proto.getUserPermissionsCount(); i++) { 799 userPerm = proto.getUserPermissions(i); 800 String username = userPerm.getUser().toStringUtf8(); 801 for (int j = 0; j < userPerm.getPermissionsCount(); j++) { 802 userPermission.put(username, 803 new UserPermission(username, toPermission(userPerm.getPermissions(j)))); 804 } 805 } 806 return userPermission; 807 } 808 809 /** 810 * Convert a protobuf UserTablePermissions to a ListMultimap<Username, Permission> 811 * @param proto the proto UsersAndPermissions 812 * @return a ListMultimap with user and its permissions 813 */ 814 public static ListMultimap<String, Permission> 815 toPermission(AccessControlProtos.UsersAndPermissions proto) { 816 ListMultimap<String, Permission> perms = ArrayListMultimap.create(); 817 AccessControlProtos.UsersAndPermissions.UserPermissions userPerm; 818 for (int i = 0; i < proto.getUserPermissionsCount(); i++) { 819 userPerm = proto.getUserPermissions(i); 820 String username = userPerm.getUser().toStringUtf8(); 821 for (int j = 0; j < userPerm.getPermissionsCount(); j++) { 822 perms.put(username, toPermission(userPerm.getPermissions(j))); 823 } 824 } 825 return perms; 826 } 827 828 /** 829 * Create a request to revoke user table permissions. 830 * @param username the short user name whose permissions to be revoked 831 * @param tableName optional table name the permissions apply 832 * @param family optional column family 833 * @param qualifier optional qualifier 834 * @param actions the permissions to be revoked 835 * @return A {@link AccessControlProtos} RevokeRequest 836 */ 837 public static AccessControlProtos.RevokeRequest buildRevokeRequest(String username, 838 TableName tableName, byte[] family, byte[] qualifier, 839 AccessControlProtos.Permission.Action... actions) { 840 AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); 841 AccessControlProtos.TablePermission.Builder permissionBuilder = 842 AccessControlProtos.TablePermission.newBuilder(); 843 for (AccessControlProtos.Permission.Action a : actions) { 844 permissionBuilder.addAction(a); 845 } 846 if (tableName != null) { 847 permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName)); 848 } 849 if (family != null) { 850 permissionBuilder.setFamily(UnsafeByteOperations.unsafeWrap(family)); 851 } 852 if (qualifier != null) { 853 permissionBuilder.setQualifier(UnsafeByteOperations.unsafeWrap(qualifier)); 854 } 855 ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(permissionBuilder); 856 return AccessControlProtos.RevokeRequest.newBuilder() 857 .setUserPermission(AccessControlProtos.UserPermission.newBuilder() 858 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)) 859 .build(); 860 } 861}