View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.access;
19  
20  import java.io.IOException;
21  import java.util.Map;
22  
23  import com.google.protobuf.HBaseZeroCopyByteString;
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.classification.InterfaceStability;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HConstants;
28  import org.apache.hadoop.hbase.NamespaceDescriptor;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.client.HTable;
31  import org.apache.hadoop.hbase.client.coprocessor.Batch;
32  import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
33  import org.apache.hadoop.hbase.ipc.ServerRpcController;
34  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
35  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
36  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
37  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRequest;
38  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantResponse;
39  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest;
40  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse;
41  
42  import com.google.protobuf.ByteString;
43  
44  /**
45   * Utility client for doing access control admin operations.
46   */
47  @InterfaceAudience.Public
48  @InterfaceStability.Evolving
49  public class AccessControlClient {
50    /**
51     * Grants permission on the specified table for the specified user
52     * @param conf
53     * @param tableName
54     * @param userName
55     * @param family
56     * @param qual
57     * @param actions
58     * @return GrantResponse
59     * @throws Throwable
60     */
61    public static GrantResponse grant(Configuration conf, final TableName tableName,
62        final String userName, final byte[] family, final byte[] qual,
63        final AccessControlProtos.Permission.Action... actions) throws Throwable {
64      HTable ht = null;
65      try {
66        TableName aclTableName =
67            TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
68        ht = new HTable(conf, aclTableName.getName());
69        Batch.Call<AccessControlService, GrantResponse> callable =
70            new Batch.Call<AccessControlService, GrantResponse>() {
71          ServerRpcController controller = new ServerRpcController();
72          BlockingRpcCallback<GrantResponse> rpcCallback =
73              new BlockingRpcCallback<GrantResponse>();
74  
75          @Override
76          public GrantResponse call(AccessControlService service) throws IOException {
77            GrantRequest.Builder builder = GrantRequest.newBuilder();
78            AccessControlProtos.Permission.Builder ret =
79                AccessControlProtos.Permission.newBuilder();
80            AccessControlProtos.TablePermission.Builder permissionBuilder =
81                AccessControlProtos.TablePermission
82                .newBuilder();
83            for (AccessControlProtos.Permission.Action a : actions) {
84              permissionBuilder.addAction(a);
85            }
86            permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
87  
88            if (family != null) {
89              permissionBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
90            }
91            if (qual != null) {
92              permissionBuilder.setQualifier(HBaseZeroCopyByteString.wrap(qual));
93            }
94            ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
95                permissionBuilder);
96            builder.setUserPermission(AccessControlProtos.UserPermission.newBuilder()
97                .setUser(ByteString.copyFromUtf8(userName)).setPermission(ret));
98            service.grant(controller, builder.build(), rpcCallback);
99            return rpcCallback.get();
100         }
101       };
102       Map<byte[], GrantResponse> result = ht.coprocessorService(AccessControlService.class,
103           HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
104       return result.values().iterator().next(); // There will be exactly one
105                                                 // region for labels
106                                                 // table and so one entry in
107                                                 // result Map.
108     } finally {
109       if (ht != null) {
110         ht.close();
111       }
112     }
113   }
114 
115   /**
116    * Revokes the permission on the table
117    * @param conf
118    * @param username
119    * @param tableName
120    * @param family
121    * @param qualifier
122    * @param actions
123    * @return RevokeResponse
124    * @throws Throwable
125    */
126   public static RevokeResponse revoke(Configuration conf, final String username,
127       final TableName tableName, final byte[] family, final byte[] qualifier,
128       final AccessControlProtos.Permission.Action... actions) throws Throwable {
129     HTable ht = null;
130     try {
131       TableName aclTableName = TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR,
132           "acl");
133       ht = new HTable(conf, aclTableName.getName());
134       Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse> callable =
135           new Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse>() {
136         ServerRpcController controller = new ServerRpcController();
137         BlockingRpcCallback<AccessControlProtos.RevokeResponse> rpcCallback =
138             new BlockingRpcCallback<AccessControlProtos.RevokeResponse>();
139 
140         @Override
141         public RevokeResponse call(AccessControlService service) throws IOException {
142           AccessControlProtos.Permission.Builder ret =
143               AccessControlProtos.Permission.newBuilder();
144           AccessControlProtos.TablePermission.Builder permissionBuilder =
145               AccessControlProtos.TablePermission.newBuilder();
146           for (AccessControlProtos.Permission.Action a : actions) {
147             permissionBuilder.addAction(a);
148           }
149           if (tableName != null) {
150             permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
151           }
152           if (family != null) {
153             permissionBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
154           }
155           if (qualifier != null) {
156             permissionBuilder.setQualifier(HBaseZeroCopyByteString.wrap(qualifier));
157           }
158           ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
159               permissionBuilder);
160           RevokeRequest builder = AccessControlProtos.RevokeRequest
161               .newBuilder()
162               .setUserPermission(
163                   AccessControlProtos.UserPermission.newBuilder()
164                       .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)).build();
165           service.revoke(controller, builder, rpcCallback);
166           return rpcCallback.get();
167         }
168       };
169       Map<byte[], RevokeResponse> result = ht.coprocessorService(AccessControlService.class,
170           HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
171       return result.values().iterator().next();
172 
173     } finally {
174       if (ht != null) {
175         ht.close();
176       }
177     }
178   }
179 }