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