blob: f928dd6e2ea3d92dacafc6ef7c318cccb901d7fc [file] [log] [blame]
Brian O'Connor91d07982015-09-10 16:37:29 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Changhoon Yoonb856b812015-08-10 03:47:19 +090016package org.onosproject.security.impl;
17
18import com.google.common.collect.Lists;
19
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Service;
26
27import org.onosproject.app.ApplicationAdminService;
28import org.onosproject.app.ApplicationState;
29import org.onosproject.core.Application;
30import org.onosproject.core.ApplicationId;
31
32import org.onosproject.event.EventDeliveryService;
33import org.onosproject.event.ListenerRegistry;
34import org.onosproject.security.AppPermission;
35import org.onosproject.security.SecurityAdminService;
36import org.onosproject.security.store.SecurityModeEvent;
37import org.onosproject.security.store.SecurityModeListener;
38import org.onosproject.security.store.SecurityModeStore;
39import org.onosproject.security.store.SecurityModeStoreDelegate;
40import org.osgi.framework.BundleContext;
41import org.osgi.framework.FrameworkUtil;
42import org.osgi.framework.ServicePermission;
43import org.osgi.service.log.LogEntry;
44import org.osgi.service.log.LogListener;
45import org.osgi.service.log.LogReaderService;
46import org.osgi.service.permissionadmin.PermissionInfo;
47
48import java.security.AccessControlException;
49import java.security.Permission;
50import java.util.ArrayList;
51import java.util.List;
52import java.util.Map;
53import java.util.Set;
54import java.util.concurrent.ConcurrentHashMap;
55
56import org.osgi.service.permissionadmin.PermissionAdmin;
57import org.slf4j.Logger;
58
59import static org.slf4j.LoggerFactory.getLogger;
60
Changhoon Yoonb856b812015-08-10 03:47:19 +090061/**
62 * Security-Mode ONOS management implementation.
Brian O'Connor91d07982015-09-10 16:37:29 -070063 *
64 * Note: Activating Security-Mode ONOS has significant performance implications in Drake.
65 * See the wiki for instructions on how to activate it.
Changhoon Yoonb856b812015-08-10 03:47:19 +090066 */
67
68@Component(immediate = true)
69@Service
70public class SecurityModeManager implements SecurityAdminService {
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected SecurityModeStore store;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected ApplicationAdminService appAdminService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected LogReaderService logReaderService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected EventDeliveryService eventDispatcher;
83
84 private final Logger log = getLogger(getClass());
85
86 protected final ListenerRegistry<SecurityModeEvent, SecurityModeListener>
87 listenerRegistry = new ListenerRegistry<>();
88
89 private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate();
90
91 private SecurityLogListener securityLogListener = new SecurityLogListener();
92
93 private PermissionAdmin permissionAdmin = getPermissionAdmin();
94
Changhoon Yoonb856b812015-08-10 03:47:19 +090095 @Activate
96 public void activate() {
97
98 eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
Changhoon Yoonb856b812015-08-10 03:47:19 +090099 logReaderService.addLogListener(securityLogListener);
100
Changhoon Yoonb856b812015-08-10 03:47:19 +0900101 if (System.getSecurityManager() == null) {
102 log.warn("J2EE security manager is disabled.");
103 deactivate();
104 return;
105 }
106 if (permissionAdmin == null) {
107 log.warn("Permission Admin not found.");
108 deactivate();
109 return;
110 }
Changhoon Yoone71dfa42015-12-04 21:49:25 +0900111 store.setDelegate(delegate);
Changhoon Yoonb856b812015-08-10 03:47:19 +0900112
113 log.info("Security-Mode Started");
114 }
115
116 @Deactivate
117 public void deactivate() {
118 eventDispatcher.removeSink(SecurityModeEvent.class);
119 logReaderService.removeLogListener(securityLogListener);
120 store.unsetDelegate(delegate);
121 log.info("Stopped");
122
123 }
124
125 @Override
126 public boolean isSecured(ApplicationId appId) {
127 if (store.getState(appId) == null) {
128 store.registerApplication(appId);
129 }
130 return store.isSecured(appId);
131 }
132
133
134 @Override
135 public void review(ApplicationId appId) {
136 if (store.getState(appId) == null) {
137 store.registerApplication(appId);
138 }
139 store.reviewPolicy(appId);
140 }
141
142 @Override
143 public void acceptPolicy(ApplicationId appId) {
144 if (store.getState(appId) == null) {
145 store.registerApplication(appId);
146 }
147 store.acceptPolicy(appId, DefaultPolicyBuilder.convertToOnosPermissions(getMaximumPermissions(appId)));
148 }
149
150 @Override
151 public void register(ApplicationId appId) {
152 store.registerApplication(appId);
153 }
154
155 @Override
156 public Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId) {
157 return getPrintablePermissionMap(getMaximumPermissions(appId));
158 }
159
160 @Override
161 public Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId) {
162 return getPrintablePermissionMap(
163 DefaultPolicyBuilder.convertToJavaPermissions(store.getGrantedPermissions(appId)));
164 }
165
166 @Override
167 public Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId) {
168 return getPrintablePermissionMap(
169 DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId)));
170 }
171
172 private class SecurityLogListener implements LogListener {
173 @Override
174 public void logged(LogEntry entry) {
175 if (entry.getException() != null &&
176 entry.getException() instanceof AccessControlException) {
177 String location = entry.getBundle().getLocation();
178 Permission javaPerm =
179 ((AccessControlException) entry.getException()).getPermission();
180 org.onosproject.security.Permission permission = DefaultPolicyBuilder.getOnosPermission(javaPerm);
181 if (permission == null) {
182 log.warn("Unsupported permission requested.");
183 return;
184 }
185 store.getApplicationIds(location).stream().filter(
186 appId -> store.isSecured(appId) &&
187 appAdminService.getState(appId) == ApplicationState.ACTIVE).forEach(appId -> {
188 store.requestPermission(appId, permission);
189 print("[POLICY VIOLATION] APP: %s / Bundle: %s / Permission: %s ",
190 appId.name(), location, permission.toString());
191 });
192 }
193 }
194 }
195
196 private class InternalStoreDelegate implements SecurityModeStoreDelegate {
197 @Override
198 public void notify(SecurityModeEvent event) {
199 if (event.type() == SecurityModeEvent.Type.POLICY_ACCEPTED) {
200 setLocalPermissions(event.subject());
201 log.info("{} POLICY ACCEPTED and ENFORCED", event.subject().name());
202 } else if (event.type() == SecurityModeEvent.Type.POLICY_VIOLATED) {
203 log.info("{} POLICY VIOLATED", event.subject().name());
204 } else if (event.type() == SecurityModeEvent.Type.POLICY_REVIEWED) {
205 log.info("{} POLICY REVIEWED", event.subject().name());
206 }
207 eventDispatcher.post(event);
208 }
209 }
210
211 /**
212 * TYPES.
213 * 0 - APP_PERM
214 * 1 - ADMIN SERVICE
215 * 2 - NB_SERVICE
216 * 3 - ETC_SERVICE
217 * 4 - ETC
218 * @param perms
219 */
220 private Map<Integer, List<Permission>> getPrintablePermissionMap(List<Permission> perms) {
221 ConcurrentHashMap<Integer, List<Permission>> sortedMap = new ConcurrentHashMap<>();
222 sortedMap.put(0, new ArrayList());
223 sortedMap.put(1, new ArrayList());
224 sortedMap.put(2, new ArrayList());
225 sortedMap.put(3, new ArrayList());
226 sortedMap.put(4, new ArrayList());
227 for (Permission perm : perms) {
228 if (perm instanceof ServicePermission) {
229 if (DefaultPolicyBuilder.getNBServiceList().contains(perm.getName())) {
230 if (perm.getName().contains("Admin")) {
231 sortedMap.get(1).add(perm);
232 } else {
233 sortedMap.get(2).add(perm);
234 }
235 } else {
236 sortedMap.get(3).add(perm);
237 }
238 } else if (perm instanceof AppPermission) {
239 sortedMap.get(0).add(perm);
240 } else {
241 sortedMap.get(4).add(perm);
242 }
243 }
244 return sortedMap;
245 }
246
247 private void setLocalPermissions(ApplicationId applicationId) {
248 for (String location : store.getBundleLocations(applicationId)) {
249 permissionAdmin.setPermissions(location, permissionsToInfo(store.getGrantedPermissions(applicationId)));
250 }
251 }
252
253 private PermissionInfo[] permissionsToInfo(Set<org.onosproject.security.Permission> permissions) {
254 List<PermissionInfo> result = Lists.newArrayList();
255 for (org.onosproject.security.Permission perm : permissions) {
256 result.add(new PermissionInfo(perm.getClassName(), perm.getName(), perm.getActions()));
257 }
258 PermissionInfo[] permissionInfos = new PermissionInfo[result.size()];
259 return result.toArray(permissionInfos);
260 }
261
262
263
264 private List<Permission> getMaximumPermissions(ApplicationId appId) {
265 Application app = appAdminService.getApplication(appId);
266 if (app == null) {
267 print("Unknown application.");
268 return null;
269 }
270 List<Permission> appPerms;
271 switch (app.role()) {
272 case ADMIN:
273 appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions());
274 break;
275 case USER:
276 appPerms = DefaultPolicyBuilder.getUserApplicationPermissions(app.permissions());
277 break;
278 case UNSPECIFIED:
279 default:
280 appPerms = DefaultPolicyBuilder.getDefaultPerms();
281 break;
282 }
283
284 return appPerms;
285 }
286
287
288 private void print(String format, Object... args) {
289 System.out.println(String.format("SM-ONOS: " + format, args));
290 log.warn(String.format(format, args));
291 }
292
293 private PermissionAdmin getPermissionAdmin() {
294 BundleContext context = getBundleContext();
295 return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName()));
296 }
297
298 private BundleContext getBundleContext() {
299 return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
300
301 }
Changhoon Yoone71dfa42015-12-04 21:49:25 +0900302
303
Changhoon Yoonb856b812015-08-10 03:47:19 +0900304}