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.ArrayList;
22  import java.util.List;
23  import java.util.regex.Pattern;
24  
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.hbase.MasterNotRunningException;
29  import org.apache.hadoop.hbase.NamespaceDescriptor;
30  import org.apache.hadoop.hbase.TableName;
31  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
32  import org.apache.hadoop.hbase.classification.InterfaceAudience;
33  import org.apache.hadoop.hbase.classification.InterfaceStability;
34  import org.apache.hadoop.hbase.client.HBaseAdmin;
35  import org.apache.hadoop.hbase.client.HTable;
36  import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
37  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
38  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
39  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.BlockingInterface;
40  import org.apache.hadoop.hbase.util.Bytes;
41  
42  /**
43   * Utility client for doing access control admin operations.
44   */
45  @InterfaceAudience.Public
46  @InterfaceStability.Evolving
47  public class AccessControlClient {
48    public static final TableName ACL_TABLE_NAME =
49        TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
50  
51    private static HTable getAclTable(Configuration conf) throws IOException {
52      return new HTable(conf, ACL_TABLE_NAME);
53    }
54  
55    private static BlockingInterface getAccessControlServiceStub(HTable ht)
56        throws IOException {
57      CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
58      BlockingInterface protocol =
59          AccessControlProtos.AccessControlService.newBlockingStub(service);
60      return protocol;
61    }
62  
63  
64    /**
65     * Grants permission on the specified table for the specified user
66     * @param conf
67     * @param tableName
68     * @param userName
69     * @param family
70     * @param qual
71     * @param actions
72     * @throws Throwable
73     */
74    public static void grant(Configuration conf, final TableName tableName,
75        final String userName, final byte[] family, final byte[] qual,
76        final Permission.Action... actions) throws Throwable {
77      HTable ht = null;
78      try {
79        ht = getAclTable(conf);
80        ProtobufUtil.grant(getAccessControlServiceStub(ht), userName, tableName, family, qual,
81            actions);
82      } finally {
83        if (ht != null) {
84          ht.close();
85        }
86      }
87    }
88    /**
89     * Grants permission on the specified namespace for the specified user.
90     * @param conf
91     * @param namespace
92     * @param userName
93     * @param actions
94     * @throws Throwable
95     */
96    public static void grant(Configuration conf, final String namespace,
97        final String userName, final Permission.Action... actions) throws Throwable {
98      HTable ht = null;
99      try {
100       ht = getAclTable(conf);
101       ProtobufUtil.grant(getAccessControlServiceStub(ht), userName, namespace, actions);
102     } finally {
103       if (ht != null) {
104         ht.close();
105       }
106     }
107   }
108 
109   /**
110    * Grant global permissions for the specified user.
111    */
112   public static void grant(Configuration conf, final String userName,
113        final Permission.Action... actions) throws Throwable {
114     HTable ht = null;
115     try {
116       ht = getAclTable(conf);
117       ProtobufUtil.grant(getAccessControlServiceStub(ht), userName, actions);
118     } finally {
119       if (ht != null) {
120         ht.close();
121       }
122     }
123   }
124 
125   public static boolean isAccessControllerRunning(Configuration conf)
126       throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
127     HBaseAdmin ha = null;
128     try {
129       ha = new HBaseAdmin(conf);
130       return ha.isTableAvailable(ACL_TABLE_NAME);
131     } finally {
132       if (ha != null) {
133         ha.close();
134       }
135     }
136   }
137   /**
138    * Revokes the permission on the table
139    * @param conf
140    * @param tableName
141    * @param username
142    * @param family
143    * @param qualifier
144    * @param actions
145    * @throws Throwable
146    */
147   public static void revoke(Configuration conf, final TableName tableName,
148       final String username, final byte[] family, final byte[] qualifier,
149       final Permission.Action... actions) throws Throwable {
150     HTable ht = null;
151     try {
152       ht = getAclTable(conf);
153       ProtobufUtil.revoke(getAccessControlServiceStub(ht), username, tableName, family, qualifier,
154           actions);
155     } finally {
156       if (ht != null) {
157         ht.close();
158       }
159     }
160   }
161 
162   /**
163    * Revokes the permission on the table for the specified user.
164    * @param conf
165    * @param namespace
166    * @param userName
167    * @param actions
168    * @throws Throwable
169    */
170   public static void revoke(Configuration conf, final String namespace,
171       final String userName, final Permission.Action... actions) throws Throwable {
172     HTable ht = null;
173     try {
174       ht = getAclTable(conf);
175       ProtobufUtil.revoke(getAccessControlServiceStub(ht), userName, namespace, actions);
176     } finally {
177       if (ht != null) {
178         ht.close();
179       }
180     }
181   }
182 
183   /**
184    * Revoke global permissions for the specified user.
185    */
186   public static void revoke(Configuration conf, final String userName,
187       final Permission.Action... actions) throws Throwable {
188     HTable ht = null;
189     try {
190       ht = getAclTable(conf);
191       ProtobufUtil.revoke(getAccessControlServiceStub(ht), userName, actions);
192     } finally {
193       if (ht != null) {
194         ht.close();
195       }
196     }
197   }
198 
199   /**
200    * List all the userPermissions matching the given pattern.
201    * @param conf
202    * @param tableRegex The regular expression string to match against
203    * @return - returns an array of UserPermissions
204    * @throws Throwable
205    */
206   public static List<UserPermission> getUserPermissions(Configuration conf, String tableRegex)
207       throws Throwable {
208     List<UserPermission> permList = new ArrayList<UserPermission>();
209     HTable ht = null;
210     HBaseAdmin ha = null;
211     try {
212       ha = new HBaseAdmin(conf);
213       ht = new HTable(conf, ACL_TABLE_NAME);
214       CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
215       BlockingInterface protocol =
216           AccessControlProtos.AccessControlService.newBlockingStub(service);
217       HTableDescriptor[] htds = null;
218 
219       if (tableRegex == null || tableRegex.isEmpty()) {
220         permList = ProtobufUtil.getUserPermissions(protocol);
221       } else if (tableRegex.charAt(0) == '@') {
222         String namespace = tableRegex.substring(1);
223         permList = ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(namespace));
224       } else {
225         htds = ha.listTables(Pattern.compile(tableRegex));
226         for (HTableDescriptor hd : htds) {
227           permList.addAll(ProtobufUtil.getUserPermissions(protocol, hd.getTableName()));
228         }
229       }
230     } finally {
231       if (ht != null) {
232         ht.close();
233       }
234       if (ha != null) {
235         ha.close();
236       }
237     }
238     return permList;
239   }
240 
241 }