blob: 30b0f8bb95a6843db4cea37d9bc47523ab571222 [file] [log] [blame]
Changhoon Yoonb856b812015-08-10 03:47:19 +09001package org.onosproject.security.impl;
2
3import com.google.common.collect.Lists;
4
5import org.apache.felix.scr.annotations.Component;
6import org.apache.felix.scr.annotations.Reference;
7import org.apache.felix.scr.annotations.ReferenceCardinality;
8import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Deactivate;
10import org.apache.felix.scr.annotations.Service;
11
12import org.onosproject.app.ApplicationAdminService;
13import org.onosproject.app.ApplicationState;
14import org.onosproject.core.Application;
15import org.onosproject.core.ApplicationId;
16
17import org.onosproject.event.EventDeliveryService;
18import org.onosproject.event.ListenerRegistry;
19import org.onosproject.security.AppPermission;
20import org.onosproject.security.SecurityAdminService;
21import org.onosproject.security.store.SecurityModeEvent;
22import org.onosproject.security.store.SecurityModeListener;
23import org.onosproject.security.store.SecurityModeStore;
24import org.onosproject.security.store.SecurityModeStoreDelegate;
25import org.osgi.framework.BundleContext;
26import org.osgi.framework.FrameworkUtil;
27import org.osgi.framework.ServicePermission;
28import org.osgi.service.log.LogEntry;
29import org.osgi.service.log.LogListener;
30import org.osgi.service.log.LogReaderService;
31import org.osgi.service.permissionadmin.PermissionInfo;
32
33import java.security.AccessControlException;
34import java.security.Permission;
35import java.util.ArrayList;
36import java.util.List;
37import java.util.Map;
38import java.util.Set;
39import java.util.concurrent.ConcurrentHashMap;
40
41import org.osgi.service.permissionadmin.PermissionAdmin;
42import org.slf4j.Logger;
43
44import static org.slf4j.LoggerFactory.getLogger;
45
46
47
48/**
49 * Security-Mode ONOS management implementation.
50 */
51
52@Component(immediate = true)
53@Service
54public 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}