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.hbase.HConstants;
26  import org.apache.hadoop.hbase.HTableDescriptor;
27  import org.apache.hadoop.hbase.MasterNotRunningException;
28  import org.apache.hadoop.hbase.NamespaceDescriptor;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
31  import org.apache.hadoop.hbase.classification.InterfaceAudience;
32  import org.apache.hadoop.hbase.classification.InterfaceStability;
33  import org.apache.hadoop.hbase.client.Admin;
34  import org.apache.hadoop.hbase.client.Connection;
35  import org.apache.hadoop.hbase.client.Table;
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 BlockingInterface getAccessControlServiceStub(Table ht)
52        throws IOException {
53      CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
54      BlockingInterface protocol =
55          AccessControlProtos.AccessControlService.newBlockingStub(service);
56      return protocol;
57    }
58  
59    /**
60     * Grants permission on the specified table for the specified user
61     * @param connection The Connection instance to use
62     * @param tableName
63     * @param userName
64     * @param family
65     * @param qual
66     * @param actions
67     * @throws Throwable
68     */
69    public static void grant(Connection connection, final TableName tableName,
70        final String userName, final byte[] family, final byte[] qual,
71        final Permission.Action... actions) throws Throwable {
72      try (Table table = connection.getTable(ACL_TABLE_NAME)) {
73        ProtobufUtil.grant(getAccessControlServiceStub(table), userName, tableName, family, qual,
74            actions);
75      }
76    }
77  
78    /**
79     * Grants permission on the specified namespace for the specified user.
80     * @param connection The Connection instance to use
81     * @param namespace
82     * @param userName
83     * @param actions
84     * @throws Throwable
85     */
86    public static void grant(Connection connection, final String namespace,
87        final String userName, final Permission.Action... actions) throws Throwable {
88      try (Table table = connection.getTable(ACL_TABLE_NAME)) {
89        ProtobufUtil.grant(getAccessControlServiceStub(table), userName, namespace, actions);
90      }
91    }
92  
93    /**
94     * @param connection The Connection instance to use
95     * Grant global permissions for the specified user.
96     */
97    public static void grant(Connection connection, final String userName,
98         final Permission.Action... actions) throws Throwable {
99      try (Table table = connection.getTable(ACL_TABLE_NAME)) {
100       ProtobufUtil.grant(getAccessControlServiceStub(table), userName, actions);
101     }
102   }
103 
104   public static boolean isAccessControllerRunning(Connection connection)
105       throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
106     try (Admin admin = connection.getAdmin()) {
107       return admin.isTableAvailable(ACL_TABLE_NAME);
108     }
109   }
110 
111   /**
112    * Revokes the permission on the table
113    * @param connection The Connection instance to use
114    * @param tableName
115    * @param username
116    * @param family
117    * @param qualifier
118    * @param actions
119    * @throws Throwable
120    */
121   public static void revoke(Connection connection, final TableName tableName,
122       final String username, final byte[] family, final byte[] qualifier,
123       final Permission.Action... actions) throws Throwable {
124     try (Table table = connection.getTable(ACL_TABLE_NAME)) {
125       ProtobufUtil.revoke(getAccessControlServiceStub(table), username, tableName, family,
126           qualifier, actions);
127     }
128   }
129 
130   /**
131    * Revokes the permission on the table for the specified user.
132    * @param connection The Connection instance to use
133    * @param namespace
134    * @param userName
135    * @param actions
136    * @throws Throwable
137    */
138   public static void revoke(Connection connection, final String namespace,
139       final String userName, final Permission.Action... actions) throws Throwable {
140     try (Table table = connection.getTable(ACL_TABLE_NAME)) {
141       ProtobufUtil.revoke(getAccessControlServiceStub(table), userName, namespace, actions);
142     }
143   }
144 
145   /**
146    * Revoke global permissions for the specified user.
147    * @param connection The Connection instance to use
148    */
149   public static void revoke(Connection connection, final String userName,
150       final Permission.Action... actions) throws Throwable {
151     try (Table table = connection.getTable(ACL_TABLE_NAME)) {
152       ProtobufUtil.revoke(getAccessControlServiceStub(table), userName, actions);
153     }
154 
155   }
156 
157   /**
158    * List all the userPermissions matching the given pattern.
159    * @param connection The Connection instance to use
160    * @param tableRegex The regular expression string to match against
161    * @return - returns an array of UserPermissions
162    * @throws Throwable
163    */
164   public static List<UserPermission> getUserPermissions(Connection connection, String tableRegex)
165       throws Throwable {
166     List<UserPermission> permList = new ArrayList<UserPermission>();
167     try (Table table = connection.getTable(ACL_TABLE_NAME)) {
168       try (Admin admin = connection.getAdmin()) {
169         CoprocessorRpcChannel service = table.coprocessorService(HConstants.EMPTY_START_ROW);
170         BlockingInterface protocol =
171             AccessControlProtos.AccessControlService.newBlockingStub(service);
172         HTableDescriptor[] htds = null;
173         if (tableRegex == null || tableRegex.isEmpty()) {
174           permList = ProtobufUtil.getUserPermissions(protocol);
175         } else if (tableRegex.charAt(0) == '@') {
176           String namespace = tableRegex.substring(1);
177           permList = ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(namespace));
178         } else {
179           htds = admin.listTables(Pattern.compile(tableRegex), true);
180           for (HTableDescriptor hd : htds) {
181             permList.addAll(ProtobufUtil.getUserPermissions(protocol, hd.getTableName()));
182           }
183         }
184       }
185     }
186     return permList;
187   }
188 }