blob: 4d077bf26733724d29c5466d94394504c29a39bb [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.geode.cache.query.internal;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.Region;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.security.NotAuthorizedException;
import org.apache.geode.security.ResourcePermission;
public class RestrictedMethodInvocationAuthorizer implements MethodInvocationAuthorizer {
public static final String UNAUTHORIZED_STRING = "Unauthorized access to method: ";
@Immutable
protected static final Map<String, Set> DEFAULT_ACCEPTLIST =
Collections.unmodifiableMap(createAcceptList());
private SecurityService securityService;
// List of methods that can be invoked by
private final Map<String, Set> acceptListedMethodsToClass;
public RestrictedMethodInvocationAuthorizer(SecurityService securityService) {
this.securityService = securityService;
acceptListedMethodsToClass = DEFAULT_ACCEPTLIST;
}
private static HashMap<String, Set> createAcceptList() {
HashMap<String, Set> acceptListMap = new HashMap();
Set<Class> objectCallers = new HashSet();
objectCallers.add(Object.class);
objectCallers = Collections.unmodifiableSet(objectCallers);
acceptListMap.put("toString", objectCallers);
acceptListMap.put("equals", objectCallers);
acceptListMap.put("compareTo", objectCallers);
Set<Class> booleanCallers = new HashSet();
booleanCallers.add(Boolean.class);
booleanCallers = Collections.unmodifiableSet(booleanCallers);
acceptListMap.put("booleanValue", booleanCallers);
Set<Class> numericCallers = new HashSet();
numericCallers.add(Number.class);
numericCallers = Collections.unmodifiableSet(numericCallers);
acceptListMap.put("byteValue", numericCallers);
acceptListMap.put("intValue", numericCallers);
acceptListMap.put("doubleValue", numericCallers);
acceptListMap.put("floatValue", numericCallers);
acceptListMap.put("longValue", numericCallers);
acceptListMap.put("shortValue", numericCallers);
Set<Class> mapCallers = new HashSet();
mapCallers.add(Collection.class);
mapCallers.add(Map.class);
mapCallers = Collections.unmodifiableSet(mapCallers);
acceptListMap.put("get", mapCallers);
acceptListMap.put("entrySet", mapCallers);
acceptListMap.put("keySet", mapCallers);
acceptListMap.put("values", mapCallers);
acceptListMap.put("getEntries", mapCallers);
acceptListMap.put("getValues", mapCallers);
acceptListMap.put("containsKey", mapCallers);
Set<Class> mapEntryCallers = new HashSet();
mapEntryCallers.add(Map.Entry.class);
mapEntryCallers = Collections.unmodifiableSet(mapEntryCallers);
acceptListMap.put("getKey", mapEntryCallers);
acceptListMap.put("getValue", mapEntryCallers);
Set<Class> dateCallers = new HashSet<>();
dateCallers.add(Date.class);
dateCallers = Collections.unmodifiableSet(dateCallers);
acceptListMap.put("after", dateCallers);
acceptListMap.put("before", dateCallers);
acceptListMap.put("getNanos", dateCallers);
acceptListMap.put("getTime", dateCallers);
Set<Class> stringCallers = new HashSet<>();
stringCallers.add(String.class);
stringCallers = Collections.unmodifiableSet(stringCallers);
acceptListMap.put("charAt", stringCallers);
acceptListMap.put("codePointAt", stringCallers);
acceptListMap.put("codePointBefore", stringCallers);
acceptListMap.put("codePointCount", stringCallers);
acceptListMap.put("compareToIgnoreCase", stringCallers);
acceptListMap.put("concat", stringCallers);
acceptListMap.put("contains", stringCallers);
acceptListMap.put("contentEquals", stringCallers);
acceptListMap.put("endsWith", stringCallers);
acceptListMap.put("equalsIgnoreCase", stringCallers);
acceptListMap.put("getBytes", stringCallers);
acceptListMap.put("hashCode", stringCallers);
acceptListMap.put("indexOf", stringCallers);
acceptListMap.put("intern", stringCallers);
acceptListMap.put("isEmpty", stringCallers);
acceptListMap.put("lastIndexOf", stringCallers);
acceptListMap.put("length", stringCallers);
acceptListMap.put("matches", stringCallers);
acceptListMap.put("offsetByCodePoints", stringCallers);
acceptListMap.put("regionMatches", stringCallers);
acceptListMap.put("replace", stringCallers);
acceptListMap.put("replaceAll", stringCallers);
acceptListMap.put("replaceFirst", stringCallers);
acceptListMap.put("split", stringCallers);
acceptListMap.put("startsWith", stringCallers);
acceptListMap.put("substring", stringCallers);
acceptListMap.put("toCharArray", stringCallers);
acceptListMap.put("toLowerCase", stringCallers);
acceptListMap.put("toUpperCase", stringCallers);
acceptListMap.put("trim", stringCallers);
return acceptListMap;
}
protected Map<String, Set> getAcceptList() {
return acceptListedMethodsToClass;
}
boolean isAcceptlisted(Method method) {
String methodName = method.getName();
Set<Class> allowedClasses = acceptListedMethodsToClass.get(methodName);
if (allowedClasses == null) {
return false;
}
for (Class clazz : allowedClasses) {
if (clazz.isAssignableFrom(method.getDeclaringClass())) {
return true;
}
}
return false;
}
@Override
public void authorizeMethodInvocation(Method method, Object target) {
if (!isAcceptlisted(method)) {
throw new NotAuthorizedException(UNAUTHORIZED_STRING + method.getName());
}
authorizeRegionAccess(securityService, target);
}
private void authorizeRegionAccess(SecurityService securityService, Object target) {
if (target instanceof Region) {
String regionName = ((Region) target).getName();
securityService.authorize(ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ,
regionName);
}
}
}