mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-15 17:31:31 +02:00
ONOS-3521: SM-ONOS performance improvement
Change-Id: I8643187f2ceb35f8e0701d9e7ddb10098f05b244
This commit is contained in:
parent
9e51fd0a7e
commit
e71dfa4847
@ -16,26 +16,102 @@
|
||||
|
||||
package org.onosproject.security;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Aids SM-ONOS to perform API-level permission checking.
|
||||
*/
|
||||
@Beta
|
||||
public final class AppGuard {
|
||||
|
||||
private AppGuard() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the caller has the required permission only when security-mode is enabled.
|
||||
*
|
||||
* @param permission permission to be checked
|
||||
*/
|
||||
public static void checkPermission(AppPermission.Type permission) {
|
||||
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
System.getSecurityManager().checkPermission(new AppPermission(permission));
|
||||
if (sm == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object result = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
int contextHash = 0;
|
||||
AccessControlContext context = AccessController.getContext();
|
||||
Field f = null;
|
||||
try {
|
||||
f = context.getClass().getDeclaredField("context");
|
||||
|
||||
f.setAccessible(true);
|
||||
ProtectionDomain[] domain = (ProtectionDomain[]) f.get(context);
|
||||
for (ProtectionDomain pd : domain) {
|
||||
if (pd.getCodeSource() != null) {
|
||||
contextHash = contextHash ^ pd.getCodeSource().getLocation().hashCode();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return contextHash;
|
||||
} catch (NoSuchFieldException e) {
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (result == null) {
|
||||
sm.checkPermission(new AppPermission(permission));
|
||||
} else {
|
||||
AppPermission perm = new AppPermission(permission);
|
||||
int hash = ((int) result) ^ perm.hashCode();
|
||||
PermissionCheckCache.getInstance().checkCache(hash, perm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class PermissionCheckCache {
|
||||
|
||||
private static final Cache<Integer, Boolean> CACHE = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
private PermissionCheckCache() {
|
||||
}
|
||||
|
||||
private static class SingletonHelper {
|
||||
private static final PermissionCheckCache INSTANCE = new PermissionCheckCache();
|
||||
}
|
||||
|
||||
public static PermissionCheckCache getInstance() {
|
||||
return SingletonHelper.INSTANCE;
|
||||
}
|
||||
|
||||
public static void checkCache(int key, AppPermission perm) {
|
||||
try {
|
||||
CACHE.get(key, () -> {
|
||||
System.getSecurityManager().checkPermission(perm);
|
||||
return true;
|
||||
});
|
||||
} catch (ExecutionException e) {
|
||||
System.getSecurityManager().checkPermission(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,4 @@ public interface SecurityAdminService {
|
||||
* @return Map of list of permissions sorted by permission type
|
||||
*/
|
||||
Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId);
|
||||
|
||||
|
||||
}
|
||||
|
@ -54,11 +54,12 @@ import org.onosproject.net.topology.TopologyService;
|
||||
import org.onosproject.security.SecurityAdminService;
|
||||
import org.onosproject.store.service.StorageAdminService;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.osgi.framework.BundlePermission;
|
||||
import org.osgi.framework.CapabilityPermission;
|
||||
import org.osgi.framework.ServicePermission;
|
||||
import org.osgi.framework.PackagePermission;
|
||||
import org.osgi.framework.AdminPermission;
|
||||
import org.osgi.framework.AdaptPermission;
|
||||
import org.osgi.framework.CapabilityPermission;
|
||||
import org.osgi.framework.BundlePermission;
|
||||
import org.osgi.framework.PackagePermission;
|
||||
import org.osgi.service.cm.ConfigurationPermission;
|
||||
|
||||
import javax.net.ssl.SSLPermission;
|
||||
@ -68,6 +69,7 @@ import javax.security.auth.kerberos.DelegationPermission;
|
||||
import javax.sound.sampled.AudioPermission;
|
||||
import java.io.FilePermission;
|
||||
import java.io.SerializablePermission;
|
||||
import java.lang.reflect.ReflectPermission;
|
||||
import java.net.NetPermission;
|
||||
import java.net.SocketPermission;
|
||||
import java.security.Permissions;
|
||||
@ -159,6 +161,7 @@ public final class DefaultPolicyBuilder {
|
||||
permSet.add(new PackagePermission("*", PackagePermission.IMPORT));
|
||||
permSet.add(new AdaptPermission("*", AdaptPermission.ADAPT));
|
||||
permSet.add(new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE));
|
||||
permSet.add(new AdminPermission("*", AdminPermission.METADATA));
|
||||
return permSet;
|
||||
}
|
||||
|
||||
@ -359,6 +362,12 @@ public final class DefaultPolicyBuilder {
|
||||
} else if (permission instanceof ServicePermission) {
|
||||
return new org.onosproject.security.Permission(
|
||||
ServicePermission.class.getName(), permission.getName(), permission.getActions());
|
||||
} else if (permission instanceof AdminPermission) {
|
||||
return new org.onosproject.security.Permission(
|
||||
AdminPermission.class.getName(), permission.getName(), permission.getActions());
|
||||
} else if (permission instanceof ConfigurationPermission) {
|
||||
return new org.onosproject.security.Permission(
|
||||
ConfigurationPermission.class.getName(), permission.getName(), permission.getActions());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -416,10 +425,16 @@ public final class DefaultPolicyBuilder {
|
||||
return new PackagePermission(name, actions);
|
||||
} else if (ServicePermission.class.getName().equals(classname)) {
|
||||
return new ServicePermission(name, actions);
|
||||
} else if (AdminPermission.class.getName().equals(classname)) {
|
||||
return new AdminPermission(name, actions);
|
||||
} else if (ConfigurationPermission.class.getName().equals(classname)) {
|
||||
return new ConfigurationPermission(name, actions);
|
||||
} else if (ReflectPermission.class.getName().equals(classname)) {
|
||||
return new ReflectPermission(name, actions);
|
||||
}
|
||||
|
||||
//AllPermission, SecurityPermission, UnresolvedPermission
|
||||
//AWTPermission, AdminPermission(osgi), ReflectPermission not allowed
|
||||
//AWTPermission, ReflectPermission not allowed
|
||||
return null;
|
||||
|
||||
}
|
||||
@ -445,4 +460,3 @@ public final class DefaultPolicyBuilder {
|
||||
return permissions;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,16 +92,12 @@ public class SecurityModeManager implements SecurityAdminService {
|
||||
|
||||
private PermissionAdmin permissionAdmin = getPermissionAdmin();
|
||||
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
|
||||
eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
|
||||
// add Listeners
|
||||
logReaderService.addLogListener(securityLogListener);
|
||||
|
||||
store.setDelegate(delegate);
|
||||
|
||||
if (System.getSecurityManager() == null) {
|
||||
log.warn("J2EE security manager is disabled.");
|
||||
deactivate();
|
||||
@ -112,6 +108,7 @@ public class SecurityModeManager implements SecurityAdminService {
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
store.setDelegate(delegate);
|
||||
|
||||
log.info("Security-Mode Started");
|
||||
}
|
||||
@ -302,4 +299,6 @@ public class SecurityModeManager implements SecurityAdminService {
|
||||
return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -303,14 +303,4 @@ public class DistributedSecurityModeStore
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(SecurityModeStoreDelegate delegate) {
|
||||
super.setDelegate(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetDelegate(SecurityModeStoreDelegate delegate) {
|
||||
super.setDelegate(delegate);
|
||||
}
|
||||
}
|
||||
|
@ -101,4 +101,5 @@ public interface SecurityModeStore extends Store<SecurityModeEvent, SecurityMode
|
||||
* @param permissionSet array of PermissionInfo
|
||||
*/
|
||||
void acceptPolicy(ApplicationId appId, Set<Permission> permissionSet);
|
||||
|
||||
}
|
@ -186,6 +186,7 @@ import org.onosproject.net.resource.link.LinkResourceRequest;
|
||||
import org.onosproject.net.resource.link.MplsLabel;
|
||||
import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
|
||||
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
|
||||
import org.onosproject.security.Permission;
|
||||
import org.onosproject.store.Timestamp;
|
||||
import org.onosproject.store.service.MapEvent;
|
||||
import org.onosproject.store.service.SetEvent;
|
||||
@ -286,6 +287,7 @@ public final class KryoNamespaces {
|
||||
ApplicationState.class,
|
||||
ApplicationRole.class,
|
||||
DefaultApplication.class,
|
||||
Permission.class,
|
||||
Device.Type.class,
|
||||
Port.Type.class,
|
||||
ChassisId.class,
|
||||
|
Loading…
x
Reference in New Issue
Block a user