1 package org.onosproject.security.impl;
3 import com.google.common.collect.Lists;
5 import org.apache.felix.scr.annotations.Component;
6 import org.apache.felix.scr.annotations.Reference;
7 import org.apache.felix.scr.annotations.ReferenceCardinality;
8 import org.apache.felix.scr.annotations.Activate;
9 import org.apache.felix.scr.annotations.Deactivate;
10 import org.apache.felix.scr.annotations.Service;
12 import org.onosproject.app.ApplicationAdminService;
13 import org.onosproject.app.ApplicationState;
14 import org.onosproject.core.Application;
15 import org.onosproject.core.ApplicationId;
17 import org.onosproject.event.EventDeliveryService;
18 import org.onosproject.event.ListenerRegistry;
19 import org.onosproject.security.AppPermission;
20 import org.onosproject.security.SecurityAdminService;
21 import org.onosproject.security.store.SecurityModeEvent;
22 import org.onosproject.security.store.SecurityModeListener;
23 import org.onosproject.security.store.SecurityModeStore;
24 import org.onosproject.security.store.SecurityModeStoreDelegate;
25 import org.osgi.framework.BundleContext;
26 import org.osgi.framework.FrameworkUtil;
27 import org.osgi.framework.ServicePermission;
28 import org.osgi.service.log.LogEntry;
29 import org.osgi.service.log.LogListener;
30 import org.osgi.service.log.LogReaderService;
31 import org.osgi.service.permissionadmin.PermissionInfo;
33 import java.security.AccessControlException;
34 import java.security.Permission;
35 import java.util.ArrayList;
36 import java.util.List;
39 import java.util.concurrent.ConcurrentHashMap;
41 import org.osgi.service.permissionadmin.PermissionAdmin;
42 import org.slf4j.Logger;
44 import static org.slf4j.LoggerFactory.getLogger;
49 * Security-Mode ONOS management implementation.
52 @Component(immediate = true)
54 public class SecurityModeManager implements SecurityAdminService {
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected SecurityModeStore store;
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected ApplicationAdminService appAdminService;
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected LogReaderService logReaderService;
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected EventDeliveryService eventDispatcher;
68 private final Logger log = getLogger(getClass());
70 protected final ListenerRegistry<SecurityModeEvent, SecurityModeListener>
71 listenerRegistry = new ListenerRegistry<>();
73 private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate();
75 private SecurityLogListener securityLogListener = new SecurityLogListener();
77 private PermissionAdmin permissionAdmin = getPermissionAdmin();
81 public void activate() {
83 eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
85 logReaderService.addLogListener(securityLogListener);
87 store.setDelegate(delegate);
89 if (System.getSecurityManager() == null) {
90 log.warn("J2EE security manager is disabled.");
94 if (permissionAdmin == null) {
95 log.warn("Permission Admin not found.");
100 log.info("Security-Mode Started");
104 public void deactivate() {
105 eventDispatcher.removeSink(SecurityModeEvent.class);
106 logReaderService.removeLogListener(securityLogListener);
107 store.unsetDelegate(delegate);
113 public boolean isSecured(ApplicationId appId) {
114 if (store.getState(appId) == null) {
115 store.registerApplication(appId);
117 return store.isSecured(appId);
122 public void review(ApplicationId appId) {
123 if (store.getState(appId) == null) {
124 store.registerApplication(appId);
126 store.reviewPolicy(appId);
130 public void acceptPolicy(ApplicationId appId) {
131 if (store.getState(appId) == null) {
132 store.registerApplication(appId);
134 store.acceptPolicy(appId, DefaultPolicyBuilder.convertToOnosPermissions(getMaximumPermissions(appId)));
138 public void register(ApplicationId appId) {
139 store.registerApplication(appId);
143 public Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId) {
144 return getPrintablePermissionMap(getMaximumPermissions(appId));
148 public Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId) {
149 return getPrintablePermissionMap(
150 DefaultPolicyBuilder.convertToJavaPermissions(store.getGrantedPermissions(appId)));
154 public Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId) {
155 return getPrintablePermissionMap(
156 DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId)));
159 private class SecurityLogListener implements LogListener {
161 public void logged(LogEntry entry) {
162 if (entry.getException() != null &&
163 entry.getException() instanceof AccessControlException) {
164 String location = entry.getBundle().getLocation();
165 Permission javaPerm =
166 ((AccessControlException) entry.getException()).getPermission();
167 org.onosproject.security.Permission permission = DefaultPolicyBuilder.getOnosPermission(javaPerm);
168 if (permission == null) {
169 log.warn("Unsupported permission requested.");
172 store.getApplicationIds(location).stream().filter(
173 appId -> store.isSecured(appId) &&
174 appAdminService.getState(appId) == ApplicationState.ACTIVE).forEach(appId -> {
175 store.requestPermission(appId, permission);
176 print("[POLICY VIOLATION] APP: %s / Bundle: %s / Permission: %s ",
177 appId.name(), location, permission.toString());
183 private class InternalStoreDelegate implements SecurityModeStoreDelegate {
185 public void notify(SecurityModeEvent event) {
186 if (event.type() == SecurityModeEvent.Type.POLICY_ACCEPTED) {
187 setLocalPermissions(event.subject());
188 log.info("{} POLICY ACCEPTED and ENFORCED", event.subject().name());
189 } else if (event.type() == SecurityModeEvent.Type.POLICY_VIOLATED) {
190 log.info("{} POLICY VIOLATED", event.subject().name());
191 } else if (event.type() == SecurityModeEvent.Type.POLICY_REVIEWED) {
192 log.info("{} POLICY REVIEWED", event.subject().name());
194 eventDispatcher.post(event);
207 private Map<Integer, List<Permission>> getPrintablePermissionMap(List<Permission> perms) {
208 ConcurrentHashMap<Integer, List<Permission>> sortedMap = new ConcurrentHashMap<>();
209 sortedMap.put(0, new ArrayList());
210 sortedMap.put(1, new ArrayList());
211 sortedMap.put(2, new ArrayList());
212 sortedMap.put(3, new ArrayList());
213 sortedMap.put(4, new ArrayList());
214 for (Permission perm : perms) {
215 if (perm instanceof ServicePermission) {
216 if (DefaultPolicyBuilder.getNBServiceList().contains(perm.getName())) {
217 if (perm.getName().contains("Admin")) {
218 sortedMap.get(1).add(perm);
220 sortedMap.get(2).add(perm);
223 sortedMap.get(3).add(perm);
225 } else if (perm instanceof AppPermission) {
226 sortedMap.get(0).add(perm);
228 sortedMap.get(4).add(perm);
234 private void setLocalPermissions(ApplicationId applicationId) {
235 for (String location : store.getBundleLocations(applicationId)) {
236 permissionAdmin.setPermissions(location, permissionsToInfo(store.getGrantedPermissions(applicationId)));
240 private PermissionInfo[] permissionsToInfo(Set<org.onosproject.security.Permission> permissions) {
241 List<PermissionInfo> result = Lists.newArrayList();
242 for (org.onosproject.security.Permission perm : permissions) {
243 result.add(new PermissionInfo(perm.getClassName(), perm.getName(), perm.getActions()));
245 PermissionInfo[] permissionInfos = new PermissionInfo[result.size()];
246 return result.toArray(permissionInfos);
251 private List<Permission> getMaximumPermissions(ApplicationId appId) {
252 Application app = appAdminService.getApplication(appId);
254 print("Unknown application.");
257 List<Permission> appPerms;
258 switch (app.role()) {
260 appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions());
263 appPerms = DefaultPolicyBuilder.getUserApplicationPermissions(app.permissions());
267 appPerms = DefaultPolicyBuilder.getDefaultPerms();
275 private void print(String format, Object... args) {
276 System.out.println(String.format("SM-ONOS: " + format, args));
277 log.warn(String.format(format, args));
280 private PermissionAdmin getPermissionAdmin() {
281 BundleContext context = getBundleContext();
282 return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName()));
285 private BundleContext getBundleContext() {
286 return FrameworkUtil.getBundle(this.getClass()).getBundleContext();