Changhoon Yoon
Committed by Jonathan Hart

ONOS-4774, ONOS-4775, ONOS-4776 + some minor fixes

Change-Id: I0d3438f36f0ce9ce0152d295d6f2d749d7f13bed
......@@ -109,14 +109,12 @@ public class ReviewCommand extends AbstractShellCommand {
print("\t[Other SERVICE] " + perm.getName() + "(" + perm.getActions() + ")");
}
break;
case 4:
for (Permission perm: assortedMap.get(4)) {
default:
for (Permission perm: assortedMap.get(type)) {
print("\t[Other] " + perm.getClass().getSimpleName() +
" " + perm.getName() + " (" + perm.getActions() + ")");
" " + perm.getName() + " (" + perm.getActions() + ")");
}
break;
default:
break;
}
}
}
......
......@@ -82,7 +82,8 @@ public class AppPermission extends BasicPermission {
TUNNEL_WRITE,
TUNNEL_EVENT,
UI_READ,
UI_WRITE
UI_WRITE,
ADMIN
}
protected Type type;
......
/*
* Copyright 2015 Open Networking Laboratory
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -17,7 +17,6 @@ package org.onosproject.security.impl;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onosproject.cluster.ClusterAdminService;
import org.onosproject.cluster.ClusterMetadataService;
......@@ -33,8 +32,6 @@ import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.key.DeviceKeyAdminService;
import org.onosproject.net.key.DeviceKeyService;
import org.onosproject.net.newresource.ResourceAdminService;
import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.region.RegionAdminService;
import org.onosproject.net.region.RegionService;
import org.onosproject.net.statistic.FlowStatisticService;
......@@ -73,7 +70,6 @@ import org.onosproject.store.cluster.messaging.MessagingService;
import org.onosproject.store.primitives.PartitionAdminService;
import org.onosproject.store.primitives.PartitionService;
import org.onosproject.store.service.LogicalClockService;
import org.onosproject.store.service.MutexExecutionService;
import org.onosproject.store.service.StorageAdminService;
import org.onosproject.store.service.StorageService;
import org.onosproject.ui.UiExtensionService;
......@@ -84,6 +80,8 @@ import org.osgi.framework.CapabilityPermission;
import org.osgi.framework.BundlePermission;
import org.osgi.framework.PackagePermission;
import org.osgi.service.cm.ConfigurationPermission;
import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
import org.osgi.service.permissionadmin.PermissionAdmin;
import javax.net.ssl.SSLPermission;
import javax.security.auth.AuthPermission;
......@@ -97,10 +95,7 @@ import java.net.NetPermission;
import java.net.SocketPermission;
import java.security.Permissions;
import java.sql.SQLPermission;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.PropertyPermission;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
......@@ -114,24 +109,39 @@ public final class DefaultPolicyBuilder {
protected static ConcurrentHashMap<AppPermission.Type,
Set<String>> serviceDirectory = getServiceDirectory();
protected static List<Permission> defaultPermissions = getDefaultPerms();
protected static List<Permission> adminServicePermissions = getAdminDefaultPerms();
protected static Set<Permission> defaultPermissions = getDefaultPerms();
protected static Set<Permission> adminServicePermissions = getAdminDefaultPerms();
private DefaultPolicyBuilder(){
}
public static List<Permission> getUserApplicationPermissions(Set<org.onosproject.security.Permission> permissions) {
List<Permission> perms = Lists.newArrayList();
public static Set<Permission> getUserApplicationPermissions(Set<org.onosproject.security.Permission> permissions) {
Set<Permission> perms = Sets.newHashSet();
perms.addAll(defaultPermissions);
perms.addAll(convertToJavaPermissions(permissions));
for (Permission perm : perms) {
if (perm instanceof AppPermission && ((AppPermission) perm).getType() == ADMIN) {
perms.remove(perm);
} else if (perm instanceof ServicePermission) {
if (perm.getName().contains(SecurityAdminService.class.getName())) {
perms.remove(perm);
} else if (perm.getName().contains(PermissionAdmin.class.getName())) {
perms.remove(perm);
} else if (perm.getName().contains(ConditionalPermissionAdmin.class.getName())) {
perms.remove(perm);
}
}
}
return optimizePermissions(perms);
}
public static List<Permission> getAdminApplicationPermissions(
public static Set<Permission> getAdminApplicationPermissions(
Set<org.onosproject.security.Permission> permissions) {
List<Permission> perms = Lists.newArrayList();
Set<Permission> perms = Sets.newHashSet();
perms.addAll(defaultPermissions);
perms.addAll(adminServicePermissions);
perms.add(new AppPermission(ADMIN));
for (AppPermission.Type perm : serviceDirectory.keySet()) {
perms.add(new AppPermission(perm));
}
......@@ -139,8 +149,8 @@ public final class DefaultPolicyBuilder {
return optimizePermissions(perms);
}
public static List<Permission> convertToJavaPermissions(Set<org.onosproject.security.Permission> permissions) {
List<Permission> result = Lists.newArrayList();
public static Set<Permission> convertToJavaPermissions(Set<org.onosproject.security.Permission> permissions) {
Set<Permission> result = Sets.newHashSet();
for (org.onosproject.security.Permission perm : permissions) {
Permission javaPerm = getPermission(perm);
if (javaPerm != null) {
......@@ -153,6 +163,9 @@ public final class DefaultPolicyBuilder {
result.add(new ServicePermission(service, ServicePermission.GET));
}
}
if (ap.getType() == CONFIG_WRITE) {
result.addAll(getConfigServicePerms());
}
}
} else if (javaPerm instanceof ServicePermission) {
if (!javaPerm.getName().contains(SecurityAdminService.class.getName())) {
......@@ -167,7 +180,7 @@ public final class DefaultPolicyBuilder {
return result;
}
public static Set<org.onosproject.security.Permission> convertToOnosPermissions(List<Permission> permissions) {
public static Set<org.onosproject.security.Permission> convertToOnosPermissions(Set<Permission> permissions) {
Set<org.onosproject.security.Permission> result = Sets.newHashSet();
for (Permission perm : permissions) {
org.onosproject.security.Permission onosPerm = getOnosPermission(perm);
......@@ -178,18 +191,27 @@ public final class DefaultPolicyBuilder {
return result;
}
public static List<Permission> getDefaultPerms() {
List<Permission> permSet = Lists.newArrayList();
public static Set<Permission> getDefaultPerms() {
Set<Permission> permSet = Sets.newHashSet();
// slf4j-logging requirement
permSet.add(
new AdaptPermission("(adaptClass=org.osgi.framework.wiring.BundleRevision)", AdaptPermission.ADAPT));
// package-permissions
permSet.add(new PackagePermission("*", PackagePermission.EXPORTONLY));
permSet.add(new PackagePermission("*", PackagePermission.IMPORT));
permSet.add(new AdaptPermission("*", AdaptPermission.ADAPT));
return permSet;
}
private static Set<Permission> getConfigServicePerms() {
Set<Permission> permSet = Sets.newHashSet();
permSet.add(new AdminPermission("(name=org.onosproject.onos-core-net)", AdminPermission.METADATA));
permSet.add(new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE));
permSet.add(new AdminPermission("*", AdminPermission.METADATA));
return permSet;
}
private static List<Permission> getAdminDefaultPerms() {
List<Permission> permSet = Lists.newArrayList();
private static Set<Permission> getAdminDefaultPerms() {
Set<Permission> permSet = Sets.newHashSet();
permSet.add(new ServicePermission(ApplicationAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ClusterAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(LeadershipAdminService.class.getName(), ServicePermission.GET));
......@@ -200,11 +222,9 @@ public final class DefaultPolicyBuilder {
permSet.add(new ServicePermission(HostAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(DeviceKeyAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(LinkAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ResourceAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(RegionAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(PartitionAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(StorageAdminService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ApplicationService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ComponentConfigService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ClusterMetadataService.class.getName(), ServicePermission.GET));
......@@ -233,7 +253,7 @@ public final class DefaultPolicyBuilder {
permSet.add(new ServicePermission(LinkService.class.getName(), ServicePermission.GET));
// permSet.add(new ServicePermission(MulticastRouteService.class.getName(), ServicePermission.GET));
// permSet.add(new ServicePermission(MeterService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ResourceService.class.getName(), ServicePermission.GET));
// permSet.add(new ServicePermission(ResourceService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(PacketService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(ProxyArpService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(RegionService.class.getName(), ServicePermission.GET));
......@@ -248,7 +268,7 @@ public final class DefaultPolicyBuilder {
permSet.add(new ServicePermission(MessagingService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(PartitionService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(LogicalClockService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(MutexExecutionService.class.getName(), ServicePermission.GET));
// permSet.add(new ServicePermission(MutexExecutionService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(StorageService.class.getName(), ServicePermission.GET));
permSet.add(new ServicePermission(UiExtensionService.class.getName(), ServicePermission.GET));
......@@ -256,13 +276,22 @@ public final class DefaultPolicyBuilder {
}
public static Set<String> getNBServiceList() {
Set<String> permString = new HashSet<>();
Set<String> permString = Sets.newHashSet();
for (Permission perm : getAdminDefaultPerms()) {
permString.add(perm.getName());
}
return permString;
}
public static Set<String> getCliServiceList() {
Set<String> permString = Sets.newHashSet();
permString.add("org.apache.felix.service.command.Function");
permString.add("org.apache.karaf.shell.console.CompletableFunction");
permString.add("org.apache.karaf.shell.commands.CommandWithAction");
permString.add("org.osgi.service.blueprint.container.BlueprintContainer");
return permString;
}
private static ConcurrentHashMap<AppPermission.Type, Set<String>> getServiceDirectory() {
ConcurrentHashMap<AppPermission.Type, Set<String>> serviceDirectory = new ConcurrentHashMap<>();
......@@ -360,12 +389,12 @@ public final class DefaultPolicyBuilder {
EventDeliveryService.class.getName()));
serviceDirectory.put(EVENT_WRITE, ImmutableSet.of(
EventDeliveryService.class.getName()));
serviceDirectory.put(RESOURCE_READ, ImmutableSet.of(
ResourceService.class.getName()));
serviceDirectory.put(RESOURCE_WRITE, ImmutableSet.of(
ResourceService.class.getName()));
serviceDirectory.put(RESOURCE_EVENT, ImmutableSet.of(
ResourceService.class.getName()));
// serviceDirectory.put(RESOURCE_READ, ImmutableSet.of(
// ResourceService.class.getName()));
// serviceDirectory.put(RESOURCE_WRITE, ImmutableSet.of(
// ResourceService.class.getName()));
// serviceDirectory.put(RESOURCE_EVENT, ImmutableSet.of(
// ResourceService.class.getName()));
serviceDirectory.put(REGION_READ, ImmutableSet.of(
RegionService.class.getName()));
serviceDirectory.put(PERSISTENCE_WRITE, ImmutableSet.of(
......@@ -376,8 +405,8 @@ public final class DefaultPolicyBuilder {
PartitionService.class.getName()));
serviceDirectory.put(CLOCK_WRITE, ImmutableSet.of(
LogicalClockService.class.getName()));
serviceDirectory.put(MUTEX_WRITE, ImmutableSet.of(
MutexExecutionService.class.getName()));
// serviceDirectory.put(MUTEX_WRITE, ImmutableSet.of(
// MutexExecutionService.class.getName()));
return serviceDirectory;
}
......@@ -515,18 +544,16 @@ public final class DefaultPolicyBuilder {
return new ReflectPermission(name, actions);
}
//AllPermission, SecurityPermission, UnresolvedPermission
//AWTPermission, ReflectPermission not allowed
return null;
}
private static List<Permission> optimizePermissions(List<Permission> perms) {
private static Set<Permission> optimizePermissions(Set<Permission> perms) {
Permissions permissions = listToPermissions(perms);
return permissionsToList(permissions);
}
private static List<Permission> permissionsToList(Permissions perms) {
List<Permission> permissions = new ArrayList<>();
private static Set<Permission> permissionsToList(Permissions perms) {
Set<Permission> permissions = Sets.newHashSet();
Enumeration<Permission> e = perms.elements();
while (e.hasMoreElements()) {
permissions.add(e.nextElement());
......@@ -534,7 +561,7 @@ public final class DefaultPolicyBuilder {
return permissions;
}
private static Permissions listToPermissions(List<Permission> perms) {
private static Permissions listToPermissions(Set<Permission> perms) {
Permissions permissions = new Permissions();
for (Permission perm : perms) {
permissions.add(perm);
......
/*
* Copyright 2015 Open Networking Laboratory
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -38,15 +38,18 @@ 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.FrameworkEvent;
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.framework.FrameworkListener;
import org.osgi.service.permissionadmin.PermissionInfo;
import java.io.FilePermission;
import java.lang.reflect.ReflectPermission;
import java.net.SocketPermission;
import java.security.AccessControlException;
import java.security.Permission;
import java.security.SecurityPermission;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
......@@ -76,9 +79,6 @@ public class SecurityModeManager implements SecurityAdminService {
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());
......@@ -88,7 +88,7 @@ public class SecurityModeManager implements SecurityAdminService {
private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate();
private SecurityLogListener securityLogListener = new SecurityLogListener();
private SecurityEventListener securityEventListener = new SecurityEventListener();
private PermissionAdmin permissionAdmin = getPermissionAdmin();
......@@ -96,7 +96,7 @@ public class SecurityModeManager implements SecurityAdminService {
public void activate() {
eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
logReaderService.addLogListener(securityLogListener);
getBundleContext().addFrameworkListener(new SecurityEventListener());
if (System.getSecurityManager() == null) {
log.warn("J2EE security manager is disabled.");
......@@ -116,7 +116,7 @@ public class SecurityModeManager implements SecurityAdminService {
@Deactivate
public void deactivate() {
eventDispatcher.removeSink(SecurityModeEvent.class);
logReaderService.removeLogListener(securityLogListener);
getBundleContext().removeFrameworkListener(securityEventListener);
store.unsetDelegate(delegate);
log.info("Stopped");
......@@ -169,27 +169,32 @@ public class SecurityModeManager implements SecurityAdminService {
DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId)));
}
private class SecurityLogListener implements LogListener {
private class SecurityEventListener implements FrameworkListener {
@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());
});
public void frameworkEvent(FrameworkEvent event) {
if (event.getType() != FrameworkEvent.ERROR) {
return;
}
Throwable throwable = event.getThrowable();
if (throwable == null || !(throwable instanceof AccessControlException)) {
return;
}
String bundleLocation = event.getBundle().getLocation();
Permission nativePerm = ((AccessControlException) throwable).getPermission();
org.onosproject.security.Permission onosPerm = DefaultPolicyBuilder.getOnosPermission(nativePerm);
if (onosPerm == null) {
log.warn("Unsupported permission requested: " + nativePerm.toString());
return;
}
store.getApplicationIds(bundleLocation).stream().filter(
appId -> store.isSecured(appId) &&
appAdminService.getState(appId) == ApplicationState.ACTIVE).forEach(appId -> {
store.requestPermission(appId, onosPerm);
print("[POLICY VIOLATION] APP: %s / Bundle: %s / Permission: %s ",
appId.name(), bundleLocation, onosPerm.toString());
});
}
}
......@@ -213,32 +218,59 @@ public class SecurityModeManager implements SecurityAdminService {
* 0 - APP_PERM
* 1 - ADMIN SERVICE
* 2 - NB_SERVICE
* 3 - ETC_SERVICE
* 4 - ETC
* 3 - SB_SERVICE
* 4 - CLI_SERVICE
* 5 - ETC_SERVICE
* 6 - CRITICAL PERMISSIONS
* 7 - ETC
* @param perms
*/
private Map<Integer, List<Permission>> getPrintablePermissionMap(List<Permission> perms) {
private Map<Integer, List<Permission>> getPrintablePermissionMap(Set<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());
sortedMap.put(5, new ArrayList());
sortedMap.put(6, new ArrayList());
sortedMap.put(7, new ArrayList());
for (Permission perm : perms) {
if (perm instanceof ServicePermission) {
if (DefaultPolicyBuilder.getNBServiceList().contains(perm.getName())) {
if (perm.getName().contains("Admin")) {
if (perm instanceof AppPermission) {
sortedMap.get(0).add(perm);
} else if (perm instanceof ServicePermission) {
String permName = perm.getName().trim();
if (DefaultPolicyBuilder.getNBServiceList().contains(permName)) { // ONOS NB SERVICES
if (permName.contains("Admin")) {
sortedMap.get(1).add(perm);
} else {
sortedMap.get(2).add(perm);
}
} else {
} else if (permName.contains("org.onosproject") && permName.contains("Provider")) { //ONOS SB SERVICES
sortedMap.get(3).add(perm);
} else if (DefaultPolicyBuilder.getCliServiceList().contains(permName)) { //CLI SERVICES
sortedMap.get(4).add(perm);
} else if (permName.contains("Security")) { //CRITICAL SERVICES
sortedMap.get(6).add(perm);
} else {
sortedMap.get(5).add(perm);
}
} else if (perm instanceof AppPermission) {
sortedMap.get(0).add(perm);
} else if (perm instanceof RuntimePermission || perm instanceof SocketPermission ||
perm instanceof FilePermission || perm instanceof SecurityPermission ||
perm instanceof ReflectPermission) { // CRITICAL PERMISSIONS
sortedMap.get(6).add(perm);
} else {
sortedMap.get(4).add(perm);
boolean isDefault = false;
for (Permission dPerm : DefaultPolicyBuilder.getDefaultPerms()) {
if (perm.implies(dPerm)) {
isDefault = true;
break;
}
}
if (!isDefault) {
sortedMap.get(7).add(perm);
}
}
}
return sortedMap;
......@@ -261,13 +293,13 @@ public class SecurityModeManager implements SecurityAdminService {
private List<Permission> getMaximumPermissions(ApplicationId appId) {
private Set<Permission> getMaximumPermissions(ApplicationId appId) {
Application app = appAdminService.getApplication(appId);
if (app == null) {
print("Unknown application.");
return null;
}
List<Permission> appPerms;
Set<Permission> appPerms;
switch (app.role()) {
case ADMIN:
appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions());
......@@ -300,5 +332,4 @@ public class SecurityModeManager implements SecurityAdminService {
}
}
\ No newline at end of file
......
/*
* Copyright 2015 Open Networking Laboratory
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -88,13 +88,10 @@ public class DistributedSecurityModeStore
.register(KryoNamespaces.API)
.register(SecurityModeState.class)
.register(SecurityInfo.class)
.register(Permission.class)
.build());
private static final KryoNamespace.Builder VIOLATION_SERIALIZER = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(Permission.class);
.register(KryoNamespaces.API);
@Activate
public void activate() {
states = storageService.<ApplicationId, SecurityInfo>consistentMapBuilder()
......
......@@ -110,7 +110,7 @@ function enable_security_mode() {
mkdir -p $ONOS_STAGE/$KARAF_DIST/system/org/apache/felix/org.apache.felix.configadmin/1.6.0
cp $FELIX_CFG_ADMIN $ONOS_STAGE/$KARAF_DIST/system/org/apache/felix/org.apache.felix.configadmin/1.6.0
perl -pi.old -e "s|org.apache.felix.configadmin/1.8.0|org.apache.felix.configadmin/1.6.0|g" \
perl -pi.old -e "s|^(.*org.apache.felix.configadmin.*)|mvn\\\\:org.apache.felix/org.apache.felix.configadmin/1.6.0 = 10|" \
$ONOS_STAGE/$KARAF_DIST/etc/startup.properties
# SM-ONOS step 2: stage ONOS Felix framework security (this is already done by karaf assembly); end
......
......@@ -105,7 +105,7 @@ if [ "$SECURE" = "true" ]; then
mkdir -p $KARAF_ROOT/system/org/apache/felix/org.apache.felix.configadmin/1.6.0
cp $FELIX_CFG_ADMIN $KARAF_ROOT/system/org/apache/felix/org.apache.felix.configadmin/1.6.0
perl -pi.old -e "s|org.apache.felix.configadmin/1.8.0|org.apache.felix.configadmin/1.6.0|g" \
perl -pi.old -e "s|^(.*org.apache.felix.configadmin.*)|mvn\\\\:org.apache.felix/org.apache.felix.configadmin/1.6.0 = 10|" \
$KARAF_ROOT/etc/startup.properties
# SM-ONOS step 2: stage ONOS Felix framework security (will get downloaded on demand); end
......