mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-16 09:51:38 +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;
|
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.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.
|
* Aids SM-ONOS to perform API-level permission checking.
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public final class AppGuard {
|
public final class AppGuard {
|
||||||
|
|
||||||
private AppGuard() {
|
private AppGuard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the caller has the required permission only when security-mode is enabled.
|
* Checks if the caller has the required permission only when security-mode is enabled.
|
||||||
|
*
|
||||||
* @param permission permission to be checked
|
* @param permission permission to be checked
|
||||||
*/
|
*/
|
||||||
public static void checkPermission(AppPermission.Type permission) {
|
public static void checkPermission(AppPermission.Type permission) {
|
||||||
|
|
||||||
SecurityManager sm = System.getSecurityManager();
|
SecurityManager sm = System.getSecurityManager();
|
||||||
if (sm != null) {
|
if (sm == null) {
|
||||||
System.getSecurityManager().checkPermission(new AppPermission(permission));
|
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
|
* @return Map of list of permissions sorted by permission type
|
||||||
*/
|
*/
|
||||||
Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId);
|
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.security.SecurityAdminService;
|
||||||
import org.onosproject.store.service.StorageAdminService;
|
import org.onosproject.store.service.StorageAdminService;
|
||||||
import org.onosproject.store.service.StorageService;
|
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.ServicePermission;
|
||||||
import org.osgi.framework.PackagePermission;
|
import org.osgi.framework.AdminPermission;
|
||||||
import org.osgi.framework.AdaptPermission;
|
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 org.osgi.service.cm.ConfigurationPermission;
|
||||||
|
|
||||||
import javax.net.ssl.SSLPermission;
|
import javax.net.ssl.SSLPermission;
|
||||||
@ -68,6 +69,7 @@ import javax.security.auth.kerberos.DelegationPermission;
|
|||||||
import javax.sound.sampled.AudioPermission;
|
import javax.sound.sampled.AudioPermission;
|
||||||
import java.io.FilePermission;
|
import java.io.FilePermission;
|
||||||
import java.io.SerializablePermission;
|
import java.io.SerializablePermission;
|
||||||
|
import java.lang.reflect.ReflectPermission;
|
||||||
import java.net.NetPermission;
|
import java.net.NetPermission;
|
||||||
import java.net.SocketPermission;
|
import java.net.SocketPermission;
|
||||||
import java.security.Permissions;
|
import java.security.Permissions;
|
||||||
@ -159,6 +161,7 @@ public final class DefaultPolicyBuilder {
|
|||||||
permSet.add(new PackagePermission("*", PackagePermission.IMPORT));
|
permSet.add(new PackagePermission("*", PackagePermission.IMPORT));
|
||||||
permSet.add(new AdaptPermission("*", AdaptPermission.ADAPT));
|
permSet.add(new AdaptPermission("*", AdaptPermission.ADAPT));
|
||||||
permSet.add(new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE));
|
permSet.add(new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE));
|
||||||
|
permSet.add(new AdminPermission("*", AdminPermission.METADATA));
|
||||||
return permSet;
|
return permSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +362,12 @@ public final class DefaultPolicyBuilder {
|
|||||||
} else if (permission instanceof ServicePermission) {
|
} else if (permission instanceof ServicePermission) {
|
||||||
return new org.onosproject.security.Permission(
|
return new org.onosproject.security.Permission(
|
||||||
ServicePermission.class.getName(), permission.getName(), permission.getActions());
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
@ -416,10 +425,16 @@ public final class DefaultPolicyBuilder {
|
|||||||
return new PackagePermission(name, actions);
|
return new PackagePermission(name, actions);
|
||||||
} else if (ServicePermission.class.getName().equals(classname)) {
|
} else if (ServicePermission.class.getName().equals(classname)) {
|
||||||
return new ServicePermission(name, actions);
|
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
|
//AllPermission, SecurityPermission, UnresolvedPermission
|
||||||
//AWTPermission, AdminPermission(osgi), ReflectPermission not allowed
|
//AWTPermission, ReflectPermission not allowed
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -445,4 +460,3 @@ public final class DefaultPolicyBuilder {
|
|||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,16 +92,12 @@ public class SecurityModeManager implements SecurityAdminService {
|
|||||||
|
|
||||||
private PermissionAdmin permissionAdmin = getPermissionAdmin();
|
private PermissionAdmin permissionAdmin = getPermissionAdmin();
|
||||||
|
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public void activate() {
|
public void activate() {
|
||||||
|
|
||||||
eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
|
eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
|
||||||
// add Listeners
|
|
||||||
logReaderService.addLogListener(securityLogListener);
|
logReaderService.addLogListener(securityLogListener);
|
||||||
|
|
||||||
store.setDelegate(delegate);
|
|
||||||
|
|
||||||
if (System.getSecurityManager() == null) {
|
if (System.getSecurityManager() == null) {
|
||||||
log.warn("J2EE security manager is disabled.");
|
log.warn("J2EE security manager is disabled.");
|
||||||
deactivate();
|
deactivate();
|
||||||
@ -112,6 +108,7 @@ public class SecurityModeManager implements SecurityAdminService {
|
|||||||
deactivate();
|
deactivate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
store.setDelegate(delegate);
|
||||||
|
|
||||||
log.info("Security-Mode Started");
|
log.info("Security-Mode Started");
|
||||||
}
|
}
|
||||||
@ -302,4 +299,6 @@ public class SecurityModeManager implements SecurityAdminService {
|
|||||||
return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
|
return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -303,14 +303,4 @@ public class DistributedSecurityModeStore
|
|||||||
}
|
}
|
||||||
return locations;
|
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
|
* @param permissionSet array of PermissionInfo
|
||||||
*/
|
*/
|
||||||
void acceptPolicy(ApplicationId appId, Set<Permission> permissionSet);
|
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.MplsLabel;
|
||||||
import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
|
import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
|
||||||
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
|
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
|
||||||
|
import org.onosproject.security.Permission;
|
||||||
import org.onosproject.store.Timestamp;
|
import org.onosproject.store.Timestamp;
|
||||||
import org.onosproject.store.service.MapEvent;
|
import org.onosproject.store.service.MapEvent;
|
||||||
import org.onosproject.store.service.SetEvent;
|
import org.onosproject.store.service.SetEvent;
|
||||||
@ -286,6 +287,7 @@ public final class KryoNamespaces {
|
|||||||
ApplicationState.class,
|
ApplicationState.class,
|
||||||
ApplicationRole.class,
|
ApplicationRole.class,
|
||||||
DefaultApplication.class,
|
DefaultApplication.class,
|
||||||
|
Permission.class,
|
||||||
Device.Type.class,
|
Device.Type.class,
|
||||||
Port.Type.class,
|
Port.Type.class,
|
||||||
ChassisId.class,
|
ChassisId.class,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user