HBASE-23232 Remove rsgroup profile from pom.xml of hbase-assembly (#779)
[hbase.git] / hbase-shell / src / main / ruby / hbase / security.rb
blobf9aa2667ecd5b946ce87351e3004f54d1035f796
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     include HBaseConstants
27     def initialize(admin)
28       @admin = admin
29       @connection = @admin.getConnection
30     end
32     def close
33       @admin.close
34     end
36     #----------------------------------------------------------------------------------------------
37     def grant(user, permissions, table_name = nil, family = nil, qualifier = nil)
38       security_available?
40       # TODO: need to validate user name
42       begin
43         # Verify that the specified permission is valid
44         if permissions.nil? || permissions.empty?
45           raise(ArgumentError, 'Invalid permission: no actions associated with user')
46         end
48         perm = org.apache.hadoop.hbase.security.access.Permission.new(
49           permissions.to_java_bytes
50         )
52         if !table_name.nil?
53           tablebytes = table_name.to_java_bytes
54           # check if the tablename passed is actually a namespace
55           if isNamespace?(table_name)
56             # Namespace should exist first.
57             namespace_name = table_name[1...table_name.length]
58             raise(ArgumentError, "Can't find a namespace: #{namespace_name}") unless
59               namespace_exists?(namespace_name)
61             org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
62               @connection, namespace_name, user, perm.getActions
63             )
64           else
65             # Table should exist
66             raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name)
68             tableName = org.apache.hadoop.hbase.TableName.valueOf(table_name)
69             htd = org.apache.hadoop.hbase.HTableDescriptor.new(@admin.getDescriptor(tableName))
71             unless family.nil?
72               raise(ArgumentError, "Can't find a family: #{family}") unless htd.hasFamily(family.to_java_bytes)
73             end
75             fambytes = family.to_java_bytes unless family.nil?
76             qualbytes = qualifier.to_java_bytes unless qualifier.nil?
78             org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
79               @connection, tableName, user, fambytes, qualbytes, perm.getActions
80             )
81           end
82         else
83           # invoke cp endpoint to perform access controls
84           org.apache.hadoop.hbase.security.access.AccessControlClient.grant(
85             @connection, user, perm.getActions
86           )
87         end
88       end
89     end
91     #----------------------------------------------------------------------------------------------
92     def revoke(user, table_name = nil, family = nil, qualifier = nil)
93       security_available?
95       # TODO: need to validate user name
97       begin
98         if !table_name.nil?
99           # check if the tablename passed is actually a namespace
100           if isNamespace?(table_name)
101             # Namespace should exist first.
102             namespace_name = table_name[1...table_name.length]
103             raise(ArgumentError, "Can't find a namespace: #{namespace_name}") unless namespace_exists?(namespace_name)
105             tablebytes = table_name.to_java_bytes
106             org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
107               @connection, namespace_name, user
108             )
109           else
110             # Table should exist
111             raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name)
113             tableName = org.apache.hadoop.hbase.TableName.valueOf(table_name)
114             htd = org.apache.hadoop.hbase.HTableDescriptor.new(@admin.getDescriptor(tableName))
116             unless family.nil?
117               raise(ArgumentError, "Can't find a family: #{family}") unless htd.hasFamily(family.to_java_bytes)
118             end
120             fambytes = family.to_java_bytes unless family.nil?
121             qualbytes = qualifier.to_java_bytes unless qualifier.nil?
123             org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
124               @connection, tableName, user, fambytes, qualbytes
125             )
126           end
127         else
128           perm = org.apache.hadoop.hbase.security.access.Permission.new(''.to_java_bytes)
129           org.apache.hadoop.hbase.security.access.AccessControlClient.revoke(
130             @connection, user, perm.getActions
131           )
132         end
133       end
134     end
136     #----------------------------------------------------------------------------------------------
137     def user_permission(table_regex = nil)
138       security_available?
139       all_perms = org.apache.hadoop.hbase.security.access.AccessControlClient.getUserPermissions(
140         @connection, table_regex
141       )
142       res = {}
143       count = 0
144       all_perms.each do |value|
145         user_name = value.getUser
146         permission = value.getPermission
147         table = ''
148         family = ''
149         qualifier = ''
150         if !table_regex.nil? && isNamespace?(table_regex)
151           nsPerm = permission.to_java(org.apache.hadoop.hbase.security.access.NamespacePermission)
152           namespace = nsPerm.getNamespace
153         elsif !table_regex.nil?
154           tblPerm = permission.to_java(org.apache.hadoop.hbase.security.access.TablePermission)
155           namespace = tblPerm.getNamespace
156           table = !tblPerm.getTableName.nil? ? tblPerm.getTableName.getNameAsString : ''
157           family = !tblPerm.getFamily.nil? ?
158                     org.apache.hadoop.hbase.util.Bytes.toStringBinary(tblPerm.getFamily) : ''
159           qualifier = !tblPerm.getQualifier.nil? ?
160                        org.apache.hadoop.hbase.util.Bytes.toStringBinary(tblPerm.getQualifier) : ''
161         end
163         action = org.apache.hadoop.hbase.security.access.Permission.new permission.getActions
165         if block_given?
166           yield(user_name, "#{namespace},#{table},#{family},#{qualifier}: #{action}")
167         else
168           res[user_name] ||= {}
169           res[user_name]["#{family}:#{qualifier}"] = action
170         end
171         count += 1
172       end
174       (block_given? ? count : res)
175     end
177     # Does table exist?
178     def exists?(table_name)
179       @admin.tableExists(TableName.valueOf(table_name))
180     end
182     def isNamespace?(table_name)
183       table_name.start_with?('@')
184     end
186     # Does Namespace exist
187     def namespace_exists?(namespace_name)
188       return !@admin.getNamespaceDescriptor(namespace_name).nil?
189     rescue org.apache.hadoop.hbase.NamespaceNotFoundException => e
190       return false
191     end
193     # Make sure that security features are available
194     def security_available?
195       caps = []
196       begin
197         # Try the getSecurityCapabilities API where supported.
198         # We only need to look at AUTHORIZATION, the AccessController doesn't support
199         # CELL_AUTHORIZATION without AUTHORIZATION also available.
200         caps = @admin.getSecurityCapabilities
201       rescue
202         # If we are unable to use getSecurityCapabilities, fall back with a check for
203         # deployment of the ACL table
204         raise(ArgumentError, 'DISABLED: Security features are not available') unless \
205           exists?(org.apache.hadoop.hbase.security.access.PermissionStorage::ACL_TABLE_NAME.getNameAsString)
206         return
207       end
208       raise(ArgumentError, 'DISABLED: Security features are not available') unless \
209         caps.include? org.apache.hadoop.hbase.client.security.SecurityCapability::AUTHORIZATION
210     end
211   end