blob: 60282e63e64fb2a326f7abcc2904d5247606c1d4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sentry.provider.file;
import static org.apache.sentry.provider.file.PolicyFileConstants.AUTHORIZABLE_JOINER;
import static org.apache.sentry.provider.file.PolicyFileConstants.KV_JOINER;
import static org.apache.sentry.provider.file.PolicyFileConstants.PRIVILEGE_NAME;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.apache.sentry.core.Action;
import org.apache.sentry.core.Authorizable;
import org.apache.sentry.core.AuthorizationProvider;
import org.apache.sentry.core.Database;
import org.apache.sentry.core.Server;
import org.apache.sentry.core.ServerResource;
import org.apache.sentry.core.Subject;
import org.apache.sentry.core.Table;
import org.apache.shiro.authz.Permission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public abstract class ResourceAuthorizationProvider implements AuthorizationProvider {
private static final Logger LOGGER = LoggerFactory
.getLogger(ResourceAuthorizationProvider.class);
private final GroupMappingService groupService;
private final PolicyEngine policy;
public ResourceAuthorizationProvider(PolicyEngine policy,
GroupMappingService groupService) {
this.policy = policy;
this.groupService = groupService;
}
@Override
public boolean hasAccess(Subject subject, Server server, Database database,
Table table, EnumSet<Action> actions) {
List<Authorizable> authorizables = Lists.newArrayList();
authorizables.add(server);
authorizables.add(database);
authorizables.add(table);
return hasAccess(subject, authorizables, actions);
}
@Override
public boolean hasAccess(Subject subject, Server server,
ServerResource serverResource, EnumSet<Action> actions) {
throw new UnsupportedOperationException("Deprecated");
}
/***
* @param subject: UserID to validate privileges
* @param authorizableHierarchy : List of object according to namespace hierarchy.
* eg. Server->Db->Table or Server->Function
* The privileges will be validated from the higher to lower scope
* @param actions : Privileges to validate
* @return
* True if the subject is authorized to perform requested action on the given object
*/
@Override
public boolean hasAccess(Subject subject, List<Authorizable> authorizableHierarchy,
EnumSet<Action> actions) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("Authorization Request for " + subject + " " +
authorizableHierarchy + " and " + actions);
}
Preconditions.checkNotNull(subject, "Subject cannot be null");
Preconditions.checkNotNull(authorizableHierarchy, "Authorizable cannot be null");
Preconditions.checkArgument(!authorizableHierarchy.isEmpty(), "Authorizable cannot be empty");
Preconditions.checkNotNull(actions, "Actions cannot be null");
Preconditions.checkNotNull(!actions.isEmpty(), "Actions cannot be empty");
return doHasAccess(subject, authorizableHierarchy, actions);
}
private boolean doHasAccess(Subject subject,
List<Authorizable> authorizables, EnumSet<Action> actions) {
List<String> groups = groupService.getGroups(subject.getName());
List<String> hierarchy = new ArrayList<String>();
for (Authorizable authorizable : authorizables) {
hierarchy.add(KV_JOINER.join(authorizable.getAuthzType().name(), authorizable.getName()));
}
Iterable<Permission> permissions = getPermissions(authorizables, groups);
for (Action action : actions) {
String requestPermission = AUTHORIZABLE_JOINER.join(hierarchy);
requestPermission = AUTHORIZABLE_JOINER.join(requestPermission,
KV_JOINER.join(PRIVILEGE_NAME, action.getValue()));
for (Permission permission : permissions) {
/*
* Does the permission granted in the policy file imply the requested action?
*/
boolean result = permission.implies(new WildcardPermission(requestPermission));
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("FilePermission {}, RequestPermission {}, result {}",
new Object[]{ permission, requestPermission, result});
}
if (result) {
return true;
}
}
}
return false;
}
private Iterable<Permission> getPermissions(List<Authorizable> authorizables, List<String> groups) {
return Iterables.transform(policy.getPermissions(authorizables, groups).values(),
new Function<String, Permission>() {
@Override
public Permission apply(String permission) {
return new WildcardPermission(permission);
}
});
}
}