HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-shell / src / main / ruby / hbase / security.rb
blob652459a9668cfa1adc69101346c52b5eb147216f
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
10 #     http://www.apache.org/licenses/LICENSE-2.0
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.
19 include Java
21 # Wrapper for org.apache.hadoop.hbase.client.HBaseAdmin
23 module Hbase
24   class SecurityAdmin
25     def initialize(admin)
26       @admin = admin
27       @connection = @admin.getConnection
28     end
30     def close
31       @admin.close
32     end
34     #----------------------------------------------------------------------------------------------
35     def grant(user, permissions, table_name = nil, family = nil, qualifier = nil)
36       security_available?
38       # TODO: need to validate user name
40       begin
41         # Verify that the specified permission is valid
42         if permissions.nil? || permissions.empty?
43           raise(ArgumentError, 'Invalid permission: no actions associated with user')
44         end
46         perm = org.apache.hadoop.hbase.security.access.Permission.new(
47           permissions.to_java_bytes
48         )
50         if !table_name.nil?
51           tablebytes = table_name.to_java_bytes
52           # check if the tablename passed is actually a namespace
53           if isNamespace?(table_name)
54             # Namespace should exist first.
55             namespace_name = table_name[1...table_name.length]
56             raise(ArgumentError, "Can't find a namespace: #{namespace_name}") unless
57               namespace_exists?(namespace_name)
59             org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
60               @connection, namespace_name, user, perm.getActions
61             )
62           else
63             # Table should exist
64             raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name)
66             tableName = org.apache.hadoop.hbase.TableName.valueOf(table_name)
67             td = @admin.getDescriptor(tableName)
69             unless family.nil?
70               raise(ArgumentError, "Can't find a family: #{family}") unless td.hasColumnFamily(family.to_java_bytes)
71             end
73             fambytes = family.to_java_bytes unless family.nil?
74             qualbytes = qualifier.to_java_bytes unless qualifier.nil?
76             org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
77               @connection, tableName, user, fambytes, qualbytes, perm.getActions
78             )
79           end
80         else
81           # invoke cp endpoint to perform access controls
82           org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
83             @connection, user, perm.getActions
84           )
85         end
86       end
87     end
89     #----------------------------------------------------------------------------------------------
90     def revoke(user, table_name = nil, family = nil, qualifier = nil)
91       security_available?
93       # TODO: need to validate user name
95       begin
96         if !table_name.nil?
97           # check if the tablename passed is actually a namespace
98           if isNamespace?(table_name)
99             # Namespace should exist first.
100             namespace_name = table_name[1...table_name.length]
101             raise(ArgumentError, "Can't find a namespace: #{namespace_name}") unless namespace_exists?(namespace_name)
103             tablebytes = table_name.to_java_bytes
104             org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
105               @connection, namespace_name, user
106             )
107           else
108             # Table should exist
109             raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name)
111             tableName = org.apache.hadoop.hbase.TableName.valueOf(table_name)
112             td = @admin.getDescriptor(tableName)
114             unless family.nil?
115               raise(ArgumentError, "Can't find a family: #{family}") unless td.hasColumnFamily(family.to_java_bytes)
116             end
118             fambytes = family.to_java_bytes unless family.nil?
119             qualbytes = qualifier.to_java_bytes unless qualifier.nil?
121             org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
122               @connection, tableName, user, fambytes, qualbytes
123             )
124           end
125         else
126           perm = org.apache.hadoop.hbase.security.access.Permission.new(''.to_java_bytes)
127           org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
128             @connection, user, perm.getActions
129           )
130         end
131       end
132     end
134     #----------------------------------------------------------------------------------------------
135     def user_permission(table_regex = nil)
136       security_available?
137       all_perms = org.apache.hadoop.hbase.security.access.AccessControlClient.getUserPermissions(
138         @connection, table_regex
139       )
140       res = {}
141       count = 0
142       all_perms.each do |value|
143         user_name = value.getUser
144         permission = value.getPermission
145         table = ''
146         family = ''
147         qualifier = ''
148         if !table_regex.nil? && isNamespace?(table_regex)
149           nsPerm = permission.to_java(org.apache.hadoop.hbase.security.access.NamespacePermission)
150           namespace = nsPerm.getNamespace
151         elsif !table_regex.nil? && isTablePermission?(permission)
152           tblPerm = permission.to_java(org.apache.hadoop.hbase.security.access.TablePermission)
153           namespace = tblPerm.getNamespace
154           table = !tblPerm.getTableName.nil? ? tblPerm.getTableName.getNameAsString : ''
155           family = !tblPerm.getFamily.nil? ?
156                     org.apache.hadoop.hbase.util.Bytes.toStringBinary(tblPerm.getFamily) : ''
157           qualifier = !tblPerm.getQualifier.nil? ?
158                        org.apache.hadoop.hbase.util.Bytes.toStringBinary(tblPerm.getQualifier) : ''
159         end
161         action = org.apache.hadoop.hbase.security.access.Permission.new permission.getActions
163         if block_given?
164           yield(user_name, "#{namespace},#{table},#{family},#{qualifier}: #{action}")
165         else
166           res[user_name] ||= {}
167           res[user_name]["#{family}:#{qualifier}"] = action
168         end
169         count += 1
170       end
172       (block_given? ? count : res)
173     end
175     # Does table exist?
176     def exists?(table_name)
177       @admin.tableExists(TableName.valueOf(table_name))
178     end
180     def isNamespace?(table_name)
181       table_name.start_with?('@')
182     end
184     def isTablePermission?(permission)
185       permission.java_kind_of?(org.apache.hadoop.hbase.security.access.TablePermission)
186     end
188     # Does Namespace exist
189     def namespace_exists?(namespace_name)
190       return !@admin.getNamespaceDescriptor(namespace_name).nil?
191     rescue org.apache.hadoop.hbase.NamespaceNotFoundException => e
192       return false
193     end
195     # Make sure that security features are available
196     def security_available?
197       caps = []
198       begin
199         # Try the getSecurityCapabilities API where supported.
200         # We only need to look at AUTHORIZATION, the AccessController doesn't support
201         # CELL_AUTHORIZATION without AUTHORIZATION also available.
202         caps = @admin.getSecurityCapabilities
203       rescue
204         # If we are unable to use getSecurityCapabilities, fall back with a check for
205         # deployment of the ACL table
206         raise(ArgumentError, 'DISABLED: Security features are not available') unless \
207           exists?(org.apache.hadoop.hbase.security.access.PermissionStorage::ACL_TABLE_NAME.getNameAsString)
208         return
209       end
210       raise(ArgumentError, 'DISABLED: Security features are not available') unless \
211         caps.include? org.apache.hadoop.hbase.client.security.SecurityCapability::AUTHORIZATION
212     end
213   end