Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
AuthorizationPolicy.java
Go to the documentation of this file.
1 // Copyright 2014 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.catalog;
16 
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 
21 import org.apache.commons.net.ntp.TimeStamp;
22 import org.apache.log4j.Logger;
23 import org.apache.sentry.core.common.ActiveRoleSet;
24 import org.apache.sentry.provider.cache.PrivilegeCache;
25 
26 import com.cloudera.impala.thrift.TColumn;
27 import com.cloudera.impala.thrift.TPrivilege;
28 import com.cloudera.impala.thrift.TResultRow;
29 import com.cloudera.impala.thrift.TResultSet;
30 import com.cloudera.impala.thrift.TResultSetMetadata;
32 import com.google.common.base.Strings;
33 import com.google.common.collect.Lists;
34 import com.google.common.collect.Maps;
35 import com.google.common.collect.Sets;
36 
55 public class AuthorizationPolicy implements PrivilegeCache {
56  private static final Logger LOG = Logger.getLogger(AuthorizationPolicy.class);
57 
58  // Cache of role names (case-insensitive) to role objects.
59  private final CatalogObjectCache<Role> roleCache_ = new CatalogObjectCache<Role>();
60 
61  // Map of role ID -> role name. Used to match privileges to roles.
62  Map<Integer, String> roleIds_ = Maps.newHashMap();
63 
64  // Map of group name (case sensitive) to set of role names (case insensitive) that
65  // have been granted to this group. Kept in sync with roleCache_. Provides efficient
66  // lookups of Role by group name.
67  Map<String, Set<String>> groupsToRoles_ = Maps.newHashMap();
68 
75  public synchronized void addRole(Role role) {
76  Role existingRole = roleCache_.get(role.getName());
77  // There is already a newer version of this role in the catalog, ignore
78  // just return.
79  if (existingRole != null &&
80  existingRole.getCatalogVersion() >= role.getCatalogVersion()) return;
81 
82  // If there was an existing role that was replaced we first need to remove it.
83  if (existingRole != null) {
84  // Remove the role. This will also clean up the grantGroup mappings.
85  removeRole(existingRole.getName());
86  if (existingRole.getId() == role.getId()) {
87  // Copy the privileges from the existing role.
88  for (RolePrivilege p: existingRole.getPrivileges()) {
89  role.addPrivilege(p);
90  }
91  }
92  }
93  roleCache_.add(role);
94 
95  // Add new grants
96  for (String groupName: role.getGrantGroups()) {
97  Set<String> grantedRoles = groupsToRoles_.get(groupName);
98  if (grantedRoles == null) {
99  grantedRoles = Sets.newHashSet();
100  groupsToRoles_.put(groupName, grantedRoles);
101  }
102  grantedRoles.add(role.getName().toLowerCase());
103  }
104 
105  // Add this role to the role ID mapping
106  roleIds_.put(role.getId(), role.getName());
107  }
108 
114  public synchronized void addPrivilege(RolePrivilege privilege)
115  throws CatalogException {
116  LOG.trace("Adding privilege: " + privilege.getName() +
117  " role ID: " + privilege.getRoleId());
118  Role role = getRole(privilege.getRoleId());
119  if (role == null) {
120  throw new CatalogException(String.format("Error adding privilege: %s. Role ID " +
121  "'%d' does not exist.", privilege.getName(), privilege.getRoleId()));
122  }
123  LOG.trace("Adding privilege: " + privilege.getName() + " to role: " +
124  role.getName() + "ID: " + role.getId());
125  role.addPrivilege(privilege);
126  }
127 
134  public synchronized RolePrivilege removePrivilege(RolePrivilege privilege)
135  throws CatalogException {
136  Role role = getRole(privilege.getRoleId());
137  if (role == null) {
138  throw new CatalogException(String.format("Error removing privilege: %s. Role ID " +
139  "'%d' does not exist.", privilege.getName(), privilege.getRoleId()));
140  }
141  LOG.trace("Removing privilege: '" + privilege.getName() + "' from Role ID: " +
142  privilege.getRoleId() + " Role Name: " + role.getName());
143  return role.removePrivilege(privilege.getName());
144  }
145 
149  public synchronized List<Role> getAllRoles() {
150  return roleCache_.getValues();
151  }
152 
156  public synchronized Set<String> getAllRoleNames() {
157  return Sets.newHashSet(roleCache_.keySet());
158  }
159 
163  public synchronized Role getRole(String roleName) {
164  return roleCache_.get(roleName);
165  }
166 
170  public synchronized Role getRole(int roleId) {
171  String roleName = roleIds_.get(roleId);
172  if (roleName == null) return null;
173  return roleCache_.get(roleName);
174  }
175 
180  public synchronized RolePrivilege getPrivilege(int roleId, String privilegeName) {
181  String roleName = roleIds_.get(roleId);
182  if (roleName == null) return null;
183  Role role = roleCache_.get(roleName);
184  return role.getPrivilege(privilegeName);
185  }
186 
190  public synchronized List<Role> getGrantedRoles(String groupName) {
191  List<Role> grantedRoles = Lists.newArrayList();
192  Set<String> roleNames = groupsToRoles_.get(groupName);
193  if (roleNames != null) {
194  for (String roleName: roleNames) {
195  // TODO: verify they actually exist.
196  Role role = roleCache_.get(roleName);
197  if (role != null) grantedRoles.add(roleCache_.get(roleName));
198  }
199  }
200  return grantedRoles;
201  }
202 
207  public synchronized Role removeRole(String roleName) {
208  Role removedRole = roleCache_.remove(roleName);
209  if (removedRole == null) return null;
210  // Cleanup grant groups
211  for (String grantGroup: removedRole.getGrantGroups()) {
212  // Remove this role from all of its grant groups.
213  Set<String> roles = groupsToRoles_.get(grantGroup);
214  if (roles != null) roles.remove(roleName.toLowerCase());
215  }
216  // Cleanup role id.
217  roleIds_.remove(removedRole.getId());
218  return removedRole;
219  }
220 
226  public synchronized Role addGrantGroup(String roleName, String groupName)
227  throws CatalogException {
228  Role role = roleCache_.get(roleName);
229  if (role == null) throw new CatalogException("Role does not exist: " + roleName);
230  role.addGrantGroup(groupName);
231  Set<String> grantedRoles = groupsToRoles_.get(groupName);
232  if (grantedRoles == null) {
233  grantedRoles = Sets.newHashSet();
234  groupsToRoles_.put(groupName, grantedRoles);
235  }
236  grantedRoles.add(roleName.toLowerCase());
237  return role;
238  }
239 
245  public synchronized Role removeGrantGroup(String roleName, String groupName)
246  throws CatalogException {
247  Role role = roleCache_.get(roleName);
248  if (role == null) throw new CatalogException("Role does not exist: " + roleName);
249  role.removeGrantGroup(groupName);
250  Set<String> grantedRoles = groupsToRoles_.get(groupName);
251  if (grantedRoles != null) {
252  grantedRoles.remove(roleName.toLowerCase());
253  }
254  return role;
255  }
256 
260  @Override
261  public synchronized Set<String>
262  listPrivileges(Set<String> groups, ActiveRoleSet roleSet) {
263  Set<String> privileges = Sets.newHashSet();
264  if (roleSet != ActiveRoleSet.ALL) {
265  throw new UnsupportedOperationException("Impala does not support role subsets.");
266  }
267 
268  // Collect all privileges granted to all roles.
269  for (String groupName: groups) {
270  List<Role> grantedRoles = getGrantedRoles(groupName);
271  for (Role role: grantedRoles) {
272  for (RolePrivilege privilege: role.getPrivileges()) {
273  String authorizeable = privilege.getName();
274  if (authorizeable == null) {
275  LOG.trace("Ignoring invalid privilege: " + privilege.getName());
276  continue;
277  }
278  privileges.add(authorizeable);
279  }
280  }
281  }
282  return privileges;
283  }
284 
285  @Override
286  public void close() {
287  // Nothing to do, but required by PrivilegeCache.
288  }
289 
295  public synchronized TResultSet getRolePrivileges(String roleName, TPrivilege filter) {
296  TResultSet result = new TResultSet();
297  result.setSchema(new TResultSetMetadata());
298  result.getSchema().addToColumns(new TColumn("scope", Type.STRING.toThrift()));
299  result.getSchema().addToColumns(new TColumn("database", Type.STRING.toThrift()));
300  result.getSchema().addToColumns(new TColumn("table", Type.STRING.toThrift()));
301  result.getSchema().addToColumns(new TColumn("uri", Type.STRING.toThrift()));
302  result.getSchema().addToColumns(new TColumn("privilege", Type.STRING.toThrift()));
303  result.getSchema().addToColumns(
304  new TColumn("grant_option", Type.BOOLEAN.toThrift()));
305  result.getSchema().addToColumns(new TColumn("create_time", Type.STRING.toThrift()));
306  result.setRows(Lists.<TResultRow>newArrayList());
307 
308  Role role = getRole(roleName);
309  if (role == null) return result;
310  for (RolePrivilege p: role.getPrivileges()) {
311  TPrivilege privilege = p.toThrift();
312  if (filter != null) {
313  // Check if the privileges are targeting the same object.
314  filter.setPrivilege_level(privilege.getPrivilege_level());
315  String privName = RolePrivilege.buildRolePrivilegeName(filter);
316  if (!privName.equalsIgnoreCase(privilege.getPrivilege_name())) continue;
317  }
318  TResultRowBuilder rowBuilder = new TResultRowBuilder();
319  rowBuilder.add(privilege.getScope().toString());
320  rowBuilder.add(Strings.nullToEmpty(privilege.getDb_name()));
321  rowBuilder.add(Strings.nullToEmpty(privilege.getTable_name()));
322  rowBuilder.add(Strings.nullToEmpty(privilege.getUri()));
323  rowBuilder.add(privilege.getPrivilege_level().toString());
324  rowBuilder.add(Boolean.toString(privilege.isHas_grant_opt()));
325  if (privilege.getCreate_time_ms() == -1) {
326  rowBuilder.add(null);
327  } else {
328  rowBuilder.add(
329  TimeStamp.getNtpTime(privilege.getCreate_time_ms()).toDateString());
330  }
331  result.addToRows(rowBuilder.get());
332  }
333  return result;
334  }
335 }
synchronized void addPrivilege(RolePrivilege privilege)
List< RolePrivilege > getPrivileges()
Definition: Role.java:62
synchronized TResultSet getRolePrivileges(String roleName, TPrivilege filter)
static final ScalarType STRING
Definition: Type.java:53
synchronized RolePrivilege removePrivilege(RolePrivilege privilege)
synchronized Role removeGrantGroup(String roleName, String groupName)
static final ScalarType BOOLEAN
Definition: Type.java:46
synchronized long getCatalogVersion()
Definition: Role.java:134
synchronized Role addGrantGroup(String roleName, String groupName)
synchronized List< Role > getGrantedRoles(String groupName)
Set< String > getGrantGroups()
Definition: Role.java:125
synchronized RolePrivilege getPrivilege(int roleId, String privilegeName)
void toThrift(TColumnType container)
synchronized Set< String > listPrivileges(Set< String > groups, ActiveRoleSet roleSet)