diff options
Diffstat (limited to 'framework/src/onos/core/security/src/main/java/org/onosproject/security/impl/SecurityModeManager.java')
-rw-r--r-- | framework/src/onos/core/security/src/main/java/org/onosproject/security/impl/SecurityModeManager.java | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/framework/src/onos/core/security/src/main/java/org/onosproject/security/impl/SecurityModeManager.java b/framework/src/onos/core/security/src/main/java/org/onosproject/security/impl/SecurityModeManager.java new file mode 100644 index 00000000..30b0f8bb --- /dev/null +++ b/framework/src/onos/core/security/src/main/java/org/onosproject/security/impl/SecurityModeManager.java @@ -0,0 +1,289 @@ +package org.onosproject.security.impl; + +import com.google.common.collect.Lists; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; + +import org.onosproject.app.ApplicationAdminService; +import org.onosproject.app.ApplicationState; +import org.onosproject.core.Application; +import org.onosproject.core.ApplicationId; + +import org.onosproject.event.EventDeliveryService; +import org.onosproject.event.ListenerRegistry; +import org.onosproject.security.AppPermission; +import org.onosproject.security.SecurityAdminService; +import org.onosproject.security.store.SecurityModeEvent; +import org.onosproject.security.store.SecurityModeListener; +import org.onosproject.security.store.SecurityModeStore; +import org.onosproject.security.store.SecurityModeStoreDelegate; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServicePermission; +import org.osgi.service.log.LogEntry; +import org.osgi.service.log.LogListener; +import org.osgi.service.log.LogReaderService; +import org.osgi.service.permissionadmin.PermissionInfo; + +import java.security.AccessControlException; +import java.security.Permission; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.osgi.service.permissionadmin.PermissionAdmin; +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; + + + +/** + * Security-Mode ONOS management implementation. + */ + +@Component(immediate = true) +@Service +public class SecurityModeManager implements SecurityAdminService { + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected SecurityModeStore store; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ApplicationAdminService appAdminService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected LogReaderService logReaderService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected EventDeliveryService eventDispatcher; + + private final Logger log = getLogger(getClass()); + + protected final ListenerRegistry<SecurityModeEvent, SecurityModeListener> + listenerRegistry = new ListenerRegistry<>(); + + private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate(); + + private SecurityLogListener securityLogListener = new SecurityLogListener(); + + 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(); + return; + } + if (permissionAdmin == null) { + log.warn("Permission Admin not found."); + deactivate(); + return; + } + + log.info("Security-Mode Started"); + } + + @Deactivate + public void deactivate() { + eventDispatcher.removeSink(SecurityModeEvent.class); + logReaderService.removeLogListener(securityLogListener); + store.unsetDelegate(delegate); + log.info("Stopped"); + + } + + @Override + public boolean isSecured(ApplicationId appId) { + if (store.getState(appId) == null) { + store.registerApplication(appId); + } + return store.isSecured(appId); + } + + + @Override + public void review(ApplicationId appId) { + if (store.getState(appId) == null) { + store.registerApplication(appId); + } + store.reviewPolicy(appId); + } + + @Override + public void acceptPolicy(ApplicationId appId) { + if (store.getState(appId) == null) { + store.registerApplication(appId); + } + store.acceptPolicy(appId, DefaultPolicyBuilder.convertToOnosPermissions(getMaximumPermissions(appId))); + } + + @Override + public void register(ApplicationId appId) { + store.registerApplication(appId); + } + + @Override + public Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId) { + return getPrintablePermissionMap(getMaximumPermissions(appId)); + } + + @Override + public Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId) { + return getPrintablePermissionMap( + DefaultPolicyBuilder.convertToJavaPermissions(store.getGrantedPermissions(appId))); + } + + @Override + public Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId) { + return getPrintablePermissionMap( + DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId))); + } + + private class SecurityLogListener implements LogListener { + @Override + public void logged(LogEntry entry) { + if (entry.getException() != null && + entry.getException() instanceof AccessControlException) { + String location = entry.getBundle().getLocation(); + Permission javaPerm = + ((AccessControlException) entry.getException()).getPermission(); + org.onosproject.security.Permission permission = DefaultPolicyBuilder.getOnosPermission(javaPerm); + if (permission == null) { + log.warn("Unsupported permission requested."); + return; + } + store.getApplicationIds(location).stream().filter( + appId -> store.isSecured(appId) && + appAdminService.getState(appId) == ApplicationState.ACTIVE).forEach(appId -> { + store.requestPermission(appId, permission); + print("[POLICY VIOLATION] APP: %s / Bundle: %s / Permission: %s ", + appId.name(), location, permission.toString()); + }); + } + } + } + + private class InternalStoreDelegate implements SecurityModeStoreDelegate { + @Override + public void notify(SecurityModeEvent event) { + if (event.type() == SecurityModeEvent.Type.POLICY_ACCEPTED) { + setLocalPermissions(event.subject()); + log.info("{} POLICY ACCEPTED and ENFORCED", event.subject().name()); + } else if (event.type() == SecurityModeEvent.Type.POLICY_VIOLATED) { + log.info("{} POLICY VIOLATED", event.subject().name()); + } else if (event.type() == SecurityModeEvent.Type.POLICY_REVIEWED) { + log.info("{} POLICY REVIEWED", event.subject().name()); + } + eventDispatcher.post(event); + } + } + + /** + * TYPES. + * 0 - APP_PERM + * 1 - ADMIN SERVICE + * 2 - NB_SERVICE + * 3 - ETC_SERVICE + * 4 - ETC + * @param perms + */ + private Map<Integer, List<Permission>> getPrintablePermissionMap(List<Permission> perms) { + ConcurrentHashMap<Integer, List<Permission>> sortedMap = new ConcurrentHashMap<>(); + sortedMap.put(0, new ArrayList()); + sortedMap.put(1, new ArrayList()); + sortedMap.put(2, new ArrayList()); + sortedMap.put(3, new ArrayList()); + sortedMap.put(4, new ArrayList()); + for (Permission perm : perms) { + if (perm instanceof ServicePermission) { + if (DefaultPolicyBuilder.getNBServiceList().contains(perm.getName())) { + if (perm.getName().contains("Admin")) { + sortedMap.get(1).add(perm); + } else { + sortedMap.get(2).add(perm); + } + } else { + sortedMap.get(3).add(perm); + } + } else if (perm instanceof AppPermission) { + sortedMap.get(0).add(perm); + } else { + sortedMap.get(4).add(perm); + } + } + return sortedMap; + } + + private void setLocalPermissions(ApplicationId applicationId) { + for (String location : store.getBundleLocations(applicationId)) { + permissionAdmin.setPermissions(location, permissionsToInfo(store.getGrantedPermissions(applicationId))); + } + } + + private PermissionInfo[] permissionsToInfo(Set<org.onosproject.security.Permission> permissions) { + List<PermissionInfo> result = Lists.newArrayList(); + for (org.onosproject.security.Permission perm : permissions) { + result.add(new PermissionInfo(perm.getClassName(), perm.getName(), perm.getActions())); + } + PermissionInfo[] permissionInfos = new PermissionInfo[result.size()]; + return result.toArray(permissionInfos); + } + + + + private List<Permission> getMaximumPermissions(ApplicationId appId) { + Application app = appAdminService.getApplication(appId); + if (app == null) { + print("Unknown application."); + return null; + } + List<Permission> appPerms; + switch (app.role()) { + case ADMIN: + appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions()); + break; + case USER: + appPerms = DefaultPolicyBuilder.getUserApplicationPermissions(app.permissions()); + break; + case UNSPECIFIED: + default: + appPerms = DefaultPolicyBuilder.getDefaultPerms(); + break; + } + + return appPerms; + } + + + private void print(String format, Object... args) { + System.out.println(String.format("SM-ONOS: " + format, args)); + log.warn(String.format(format, args)); + } + + private PermissionAdmin getPermissionAdmin() { + BundleContext context = getBundleContext(); + return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName())); + } + + private BundleContext getBundleContext() { + return FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + + } +}
\ No newline at end of file |