30b0f8bb95a6843db4cea37d9bc47523ab571222
[onosfw.git] /
1 package org.onosproject.security.impl;
2
3 import com.google.common.collect.Lists;
4
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;
11
12 import org.onosproject.app.ApplicationAdminService;
13 import org.onosproject.app.ApplicationState;
14 import org.onosproject.core.Application;
15 import org.onosproject.core.ApplicationId;
16
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;
32
33 import java.security.AccessControlException;
34 import java.security.Permission;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.concurrent.ConcurrentHashMap;
40
41 import org.osgi.service.permissionadmin.PermissionAdmin;
42 import org.slf4j.Logger;
43
44 import static org.slf4j.LoggerFactory.getLogger;
45
46
47
48 /**
49  * Security-Mode ONOS management implementation.
50  */
51
52 @Component(immediate = true)
53 @Service
54 public class SecurityModeManager implements SecurityAdminService {
55
56     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57     protected SecurityModeStore store;
58
59     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60     protected ApplicationAdminService appAdminService;
61
62     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63     protected LogReaderService logReaderService;
64
65     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66     protected EventDeliveryService eventDispatcher;
67
68     private final Logger log = getLogger(getClass());
69
70     protected final ListenerRegistry<SecurityModeEvent, SecurityModeListener>
71             listenerRegistry = new ListenerRegistry<>();
72
73     private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate();
74
75     private SecurityLogListener securityLogListener = new SecurityLogListener();
76
77     private PermissionAdmin permissionAdmin = getPermissionAdmin();
78
79
80     @Activate
81     public void activate() {
82
83         eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
84         // add Listeners
85         logReaderService.addLogListener(securityLogListener);
86
87         store.setDelegate(delegate);
88
89         if (System.getSecurityManager() == null) {
90             log.warn("J2EE security manager is disabled.");
91             deactivate();
92             return;
93         }
94         if (permissionAdmin == null) {
95             log.warn("Permission Admin not found.");
96             deactivate();
97             return;
98         }
99
100         log.info("Security-Mode Started");
101     }
102
103     @Deactivate
104     public void deactivate() {
105         eventDispatcher.removeSink(SecurityModeEvent.class);
106         logReaderService.removeLogListener(securityLogListener);
107         store.unsetDelegate(delegate);
108         log.info("Stopped");
109
110     }
111
112     @Override
113     public boolean isSecured(ApplicationId appId) {
114         if (store.getState(appId) == null) {
115             store.registerApplication(appId);
116         }
117         return store.isSecured(appId);
118     }
119
120
121     @Override
122     public void review(ApplicationId appId) {
123         if (store.getState(appId) == null) {
124             store.registerApplication(appId);
125         }
126         store.reviewPolicy(appId);
127     }
128
129     @Override
130     public void acceptPolicy(ApplicationId appId) {
131         if (store.getState(appId) == null) {
132             store.registerApplication(appId);
133         }
134         store.acceptPolicy(appId, DefaultPolicyBuilder.convertToOnosPermissions(getMaximumPermissions(appId)));
135     }
136
137     @Override
138     public void register(ApplicationId appId) {
139         store.registerApplication(appId);
140     }
141
142     @Override
143     public Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId) {
144         return getPrintablePermissionMap(getMaximumPermissions(appId));
145     }
146
147     @Override
148     public Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId) {
149         return getPrintablePermissionMap(
150                 DefaultPolicyBuilder.convertToJavaPermissions(store.getGrantedPermissions(appId)));
151     }
152
153     @Override
154     public Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId) {
155         return getPrintablePermissionMap(
156                 DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId)));
157     }
158
159     private class SecurityLogListener implements LogListener {
160         @Override
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.");
170                     return;
171                 }
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());
178                 });
179             }
180         }
181     }
182
183     private class InternalStoreDelegate implements SecurityModeStoreDelegate {
184         @Override
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());
193             }
194             eventDispatcher.post(event);
195         }
196     }
197
198     /**
199      * TYPES.
200      * 0 - APP_PERM
201      * 1 - ADMIN SERVICE
202      * 2 - NB_SERVICE
203      * 3 - ETC_SERVICE
204      * 4 - ETC
205      * @param perms
206      */
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);
219                     } else {
220                         sortedMap.get(2).add(perm);
221                     }
222                 } else {
223                     sortedMap.get(3).add(perm);
224                 }
225             } else if (perm instanceof AppPermission) {
226                 sortedMap.get(0).add(perm);
227             } else {
228                 sortedMap.get(4).add(perm);
229             }
230         }
231         return sortedMap;
232     }
233
234     private void setLocalPermissions(ApplicationId applicationId) {
235         for (String location : store.getBundleLocations(applicationId)) {
236             permissionAdmin.setPermissions(location, permissionsToInfo(store.getGrantedPermissions(applicationId)));
237         }
238     }
239
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()));
244         }
245         PermissionInfo[] permissionInfos = new PermissionInfo[result.size()];
246         return result.toArray(permissionInfos);
247     }
248
249
250
251     private List<Permission> getMaximumPermissions(ApplicationId appId) {
252         Application app = appAdminService.getApplication(appId);
253         if (app == null) {
254             print("Unknown application.");
255             return null;
256         }
257         List<Permission> appPerms;
258         switch (app.role()) {
259             case ADMIN:
260                 appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions());
261                 break;
262             case USER:
263                 appPerms = DefaultPolicyBuilder.getUserApplicationPermissions(app.permissions());
264                 break;
265             case UNSPECIFIED:
266             default:
267                 appPerms = DefaultPolicyBuilder.getDefaultPerms();
268                 break;
269         }
270
271         return appPerms;
272     }
273
274
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));
278     }
279
280     private PermissionAdmin getPermissionAdmin() {
281         BundleContext context = getBundleContext();
282         return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName()));
283     }
284
285     private BundleContext getBundleContext() {
286         return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
287
288     }
289 }