Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
AuthorizationChecker.java
Go to the documentation of this file.
1 // Copyright 2013 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.authorization;
16 
17 import java.util.EnumSet;
18 import java.util.List;
19 import java.util.Set;
20 
21 import org.apache.commons.lang.reflect.ConstructorUtils;
22 import org.apache.sentry.core.common.ActiveRoleSet;
23 import org.apache.sentry.core.common.Subject;
24 import org.apache.sentry.core.model.db.DBModelAction;
25 import org.apache.sentry.core.model.db.DBModelAuthorizable;
26 import org.apache.sentry.policy.db.SimpleDBPolicyEngine;
27 import org.apache.sentry.provider.cache.SimpleCacheProviderBackend;
28 import org.apache.sentry.provider.common.ProviderBackend;
29 import org.apache.sentry.provider.common.ProviderBackendContext;
30 import org.apache.sentry.provider.common.ResourceAuthorizationProvider;
31 import org.apache.sentry.provider.file.SimpleFileProviderBackend;
32 
35 import com.google.common.base.Preconditions;
36 import com.google.common.collect.Lists;
37 
38 /*
39  * Class used to check whether a user has access to a given resource.
40  */
41 public class AuthorizationChecker {
42  private final ResourceAuthorizationProvider provider_;
45 
46  /*
47  * Creates a new AuthorizationChecker based on the config values.
48  */
50  Preconditions.checkNotNull(config);
51  config_ = config;
52  if (config.isEnabled()) {
54  provider_ = createProvider(config, policy);
55  Preconditions.checkNotNull(provider_);
56  } else {
57  provider_ = null;
58  server_ = null;
59  }
60  }
61 
62  /*
63  * Creates a new ResourceAuthorizationProvider based on the given configuration.
64  */
65  private static ResourceAuthorizationProvider createProvider(AuthorizationConfig config,
66  AuthorizationPolicy policy) {
67  try {
68  ProviderBackend providerBe;
69  // Create the appropriate backend provider.
70  if (config.isFileBasedPolicy()) {
71  providerBe = new SimpleFileProviderBackend(config.getSentryConfig().getConfig(),
72  config.getPolicyFile());
73  } else {
74  // Note: The second parameter to the ProviderBackend is a "resourceFile" path
75  // which is not used by Impala. We cannot pass 'null' so instead pass an empty
76  // string.
77  providerBe = new SimpleCacheProviderBackend(config.getSentryConfig().getConfig(),
78  "");
79  Preconditions.checkNotNull(policy);
80  ProviderBackendContext context = new ProviderBackendContext();
81  context.setBindingHandle(policy);
82  providerBe.initialize(context);
83  }
84 
85  SimpleDBPolicyEngine engine =
86  new SimpleDBPolicyEngine(config.getServerName(), providerBe);
87 
88  // Try to create an instance of the specified policy provider class.
89  // Re-throw any exceptions that are encountered.
90  String policyFile = config.getPolicyFile() == null ? "" : config.getPolicyFile();
91  return (ResourceAuthorizationProvider) ConstructorUtils.invokeConstructor(
92  Class.forName(config.getPolicyProviderClassName()),
93  new Object[] {policyFile, engine});
94  } catch (Exception e) {
95  // Re-throw as unchecked exception.
96  throw new IllegalStateException(
97  "Error creating ResourceAuthorizationProvider: ", e);
98  }
99  }
100 
101  /*
102  * Returns the configuration used to create this AuthorizationProvider.
103  */
104  public AuthorizationConfig getConfig() { return config_; }
105 
111  public Set<String> getUserGroups(User user) {
112  return provider_.getGroupMapping().getGroups(user.getShortName());
113  }
114 
119  public void checkAccess(User user, PrivilegeRequest privilegeRequest)
120  throws AuthorizationException {
121  Preconditions.checkNotNull(privilegeRequest);
122 
123  if (!hasAccess(user, privilegeRequest)) {
124  if (privilegeRequest.getAuthorizeable() instanceof AuthorizeableFn) {
125  throw new AuthorizationException(String.format(
126  "User '%s' does not have privileges to CREATE/DROP functions.",
127  user.getName()));
128  }
129 
130  Privilege privilege = privilegeRequest.getPrivilege();
132  .contains(privilege)) {
133  throw new AuthorizationException(String.format(
134  "User '%s' does not have privileges to access: %s",
135  user.getName(), privilegeRequest.getName()));
136  } else {
137  throw new AuthorizationException(String.format(
138  "User '%s' does not have privileges to execute '%s' on: %s",
139  user.getName(), privilege, privilegeRequest.getName()));
140  }
141  }
142  }
143 
144  /*
145  * Returns true if the given user has permission to execute the given
146  * request, false otherwise. Always returns true if authorization is disabled.
147  */
148  public boolean hasAccess(User user, PrivilegeRequest request) {
149  Preconditions.checkNotNull(user);
150  Preconditions.checkNotNull(request);
151 
152  // If authorization is not enabled the user will always have access. If this is
153  // an internal request, the user will always have permission.
154  if (!config_.isEnabled() || user instanceof ImpalaInternalAdminUser) {
155  return true;
156  }
157 
158  EnumSet<DBModelAction> actions = request.getPrivilege().getHiveActions();
159 
160  List<DBModelAuthorizable> authorizeables = Lists.newArrayList(
161  server_.getHiveAuthorizeableHierarchy());
162  // If request.getAuthorizeable() is null, the request is for server-level permission.
163  if (request.getAuthorizeable() != null) {
164  authorizeables.addAll(request.getAuthorizeable().getHiveAuthorizeableHierarchy());
165  }
166 
167  // The Hive Access API does not currently provide a way to check if the user
168  // has any privileges on a given resource.
169  if (request.getPrivilege().getAnyOf()) {
170  for (DBModelAction action: actions) {
171  if (provider_.hasAccess(new Subject(user.getShortName()), authorizeables,
172  EnumSet.of(action), ActiveRoleSet.ALL)) {
173  return true;
174  }
175  }
176  return false;
177  } else if (request.getPrivilege() == Privilege.CREATE && authorizeables.size() > 1) {
178  // CREATE on an object requires CREATE on the parent,
179  // so don't check access on the object we're creating.
180  authorizeables.remove(authorizeables.size() - 1);
181  }
182  return provider_.hasAccess(new Subject(user.getShortName()), authorizeables, actions,
183  ActiveRoleSet.ALL);
184  }
185 }
boolean hasAccess(User user, PrivilegeRequest request)
void checkAccess(User user, PrivilegeRequest privilegeRequest)
static ResourceAuthorizationProvider createProvider(AuthorizationConfig config, AuthorizationPolicy policy)
AuthorizationChecker(AuthorizationConfig config, AuthorizationPolicy policy)