Changhoon Yoon
Committed by Gerrit Code Review

ONOS-1858, ONOS-1857, ONOS-1860, ONOS-1862, ONOS-1898 : SM-ONOS

Change-Id: I206e72521cf663466bfcc612e1896bb22d87da06
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.security;
import org.apache.karaf.shell.console.completer.StringsCompleter;
import org.onosproject.app.ApplicationService;
import org.onosproject.cli.AbstractCompleter;
import org.onosproject.core.Application;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import static org.onosproject.cli.AbstractShellCommand.get;
/**
* Application name completer for permission command.
*/
public class PermissionApplicationNameCompleter extends AbstractCompleter {
@Override
public int complete(String buffer, int cursor, List<String> candidates) {
// Delegate string completer
StringsCompleter delegate = new StringsCompleter();
// Fetch our service and feed it's offerings to the string completer
ApplicationService service = get(ApplicationService.class);
Iterator<Application> it = service.getApplications().iterator();
SortedSet<String> strings = delegate.getStrings();
while (it.hasNext()) {
Application app = it.next();
strings.add(app.id().name());
}
// Now let the completer do the work for figuring out what to offer.
return delegate.complete(buffer, cursor, candidates);
}
}
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.security;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.Permission;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Manages application permissions.
*/
@Command(scope = "onos", name = "perm",
description = "Manages application permissions")
public class PermissionCommand extends AbstractShellCommand {
static final String ADD = "add";
static final String REMOVE = "remove";
static final String LIST = "list";
static final String CLEAR = "clear";
@Argument(index = 0, name = "command",
description = "Command name (add|remove)",
required = true, multiValued = false)
String command = null;
@Argument(index = 1, name = "name", description = "Application name",
required = true, multiValued = false)
String name = null;
@Argument(index = 2, name = "permissions", description = "List of permissions",
required = false, multiValued = true)
String[] permissions = null;
@Override
protected void execute() {
ApplicationAdminService applicationAdminService = get(ApplicationAdminService.class);
Set<Permission> newPermSet = Sets.newHashSet();
if (command.equals(ADD)) {
ApplicationId appId = applicationAdminService.getId(name);
if (appId == null) {
print("No such application: %s", name);
return;
}
Application app = applicationAdminService.getApplication(appId);
for (String perm : permissions) {
try {
Permission permission = Permission.valueOf(perm);
newPermSet.add(permission);
} catch (IllegalArgumentException e) {
print("%s is not a valid permission.", perm);
return;
}
}
Set<Permission> oldPermSet = applicationAdminService.getPermissions(appId);
if (oldPermSet != null) {
newPermSet.addAll(oldPermSet);
} else {
newPermSet.addAll(app.permissions());
}
applicationAdminService.setPermissions(appId, ImmutableSet.copyOf(newPermSet));
} else if (command.equals(REMOVE)) {
ApplicationId appId = applicationAdminService.getId(name);
Application app = applicationAdminService.getApplication(appId);
if (appId == null) {
print("No such application: %s", name);
return;
}
Set<Permission> oldPermSet = applicationAdminService.getPermissions(appId);
if (oldPermSet == null) {
oldPermSet = app.permissions();
}
Set<String> clearPermSet = Sets.newHashSet(permissions);
newPermSet.addAll(oldPermSet.stream().filter(
perm -> !clearPermSet.contains(perm.name().toUpperCase())).collect(Collectors.toList()));
applicationAdminService.setPermissions(appId, ImmutableSet.copyOf(newPermSet));
} else if (command.equals(CLEAR)) {
ApplicationId appId = applicationAdminService.getId(name);
if (appId == null) {
print("No such application: %s", name);
return;
}
applicationAdminService.setPermissions(appId, ImmutableSet.of());
print("Cleared the permission list of %s.", appId.name());
} else if (command.equals(LIST)) {
ApplicationId appId = applicationAdminService.getId(name);
if (appId == null) {
print("No such application: %s", name);
return;
}
Application app = applicationAdminService.getApplication(appId);
Set<Permission> userPermissions = applicationAdminService.getPermissions(appId);
Set<Permission> defaultPermissions = app.permissions();
print("Application Role");
print("\trole=%s", app.role().name());
if (defaultPermissions != null) {
if (!defaultPermissions.isEmpty()) {
print("Default permissions (specified in app.xml)");
for (Permission perm : defaultPermissions) {
print("\tpermission=%s", perm.name());
}
} else {
print("(No default permissions specified in app.xml)");
}
}
if (userPermissions != null) {
if (!userPermissions.isEmpty()) {
print("User permissions");
for (Permission perm : userPermissions) {
print("\tpermission=%s", perm.name());
}
} else {
print("(User has removed all the permissions");
}
}
}
}
}
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.security;
import com.google.common.collect.ImmutableList;
import org.onosproject.cli.AbstractChoicesCompleter;
import java.util.List;
import static org.onosproject.cli.security.PermissionCommand.*;
/**
* Permission command completer.
*/
public class PermissionCommandCompleter extends AbstractChoicesCompleter {
@Override
protected List<String> choices() {
return ImmutableList.of(ADD, REMOVE, CLEAR, LIST);
}
}
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.security;
import org.apache.karaf.shell.console.completer.ArgumentCompleter;
import org.onosproject.cli.AbstractChoicesCompleter;
import org.onosproject.core.Permission;
import java.util.ArrayList;
import java.util.List;
/**
* Permission Name Completer.
*/
public class PermissionNameCompleter extends AbstractChoicesCompleter {
@Override
protected List<String> choices() {
List<String> permNames = new ArrayList<>();
ArgumentCompleter.ArgumentList list = getArgumentList();
String cmd = list.getArguments()[1];
if (cmd.equals("add") || cmd.equals("remove")) {
for (Permission perm : Permission.values()) {
permNames.add(perm.name());
}
}
return permNames;
}
}
......@@ -21,6 +21,15 @@
</command>
<command>
<action class="org.onosproject.cli.security.PermissionCommand"/>
<completers>
<ref component-id="permCommandCompleter"/>
<ref component-id="permAppNameCompleter"/>
<ref component-id="permNameCompleter"/>
</completers>
</command>
<command>
<action class="org.onosproject.cli.app.ApplicationsListCommand"/>
</command>
......@@ -360,6 +369,9 @@
</command>
</command-bundle>
<bean id="permAppNameCompleter" class="org.onosproject.cli.security.PermissionApplicationNameCompleter"/>
<bean id="permCommandCompleter" class="org.onosproject.cli.security.PermissionCommandCompleter"/>
<bean id="permNameCompleter" class="org.onosproject.cli.security.PermissionNameCompleter"/>
<bean id="appCommandCompleter" class="org.onosproject.cli.app.ApplicationCommandCompleter"/>
<bean id="appNameCompleter" class="org.onosproject.cli.app.ApplicationNameCompleter"/>
<bean id="allAppNameCompleter" class="org.onosproject.cli.app.AllApplicationNamesCompleter"/>
......
......@@ -36,6 +36,7 @@
<module>common</module>
<module>net</module>
<module>store</module>
<module>security</module>
</modules>
<dependencies>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 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.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onos-security</artifactId>
<groupId>org.onosproject</groupId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>bundle</packaging>
<artifactId>onos-security-impl</artifactId>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-security-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.core</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package org.onosproject.security.impl;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.commons.collections.FastHashMap;
import org.onosproject.core.Permission;
import org.onosproject.security.util.AppPermission;
import org.osgi.service.permissionadmin.PermissionInfo;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.app.ApplicationService;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cluster.ClusterAdminService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.CoreService;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.mastership.MastershipAdminService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceClockService;
import org.onosproject.net.driver.DriverAdminService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.group.GroupService;
import org.onosproject.net.host.HostAdminService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.HostClockService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentClockService;
import org.onosproject.net.intent.PartitionService;
import org.onosproject.net.link.LinkAdminService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.proxyarp.ProxyArpService;
import org.onosproject.net.resource.LabelResourceAdminService;
import org.onosproject.net.resource.LinkResourceService;
import org.onosproject.net.resource.LabelResourceService;
import org.onosproject.net.statistic.StatisticService;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.net.tunnel.TunnelAdminService;
import org.onosproject.net.tunnel.TunnelService;
import org.onosproject.store.service.StorageAdminService;
import org.onosproject.store.service.StorageService;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.AdaptPermission;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Collectors;
public final class PolicyBuilder {
private PolicyBuilder(){
}
public static PermissionInfo[] getApplicationPermissions(HashMap<Permission, Set<String>> serviceDirectory,
Set<Permission> permissions) {
Set<PermissionInfo> permSet = Sets.newHashSet();
Collections.addAll(permSet, getDefaultPerms());
for (Permission perm : permissions) {
permSet.add(new PermissionInfo(AppPermission.class.getName(), perm.name(), ""));
permSet.addAll(serviceDirectory.get(perm).stream().map(service -> new PermissionInfo(
ServicePermission.class.getName(), service, ServicePermission.GET)).collect(Collectors.toList()));
}
PermissionInfo[] permissionInfos = new PermissionInfo[permSet.size()];
return permSet.toArray(permissionInfos);
}
public static PermissionInfo[] getAdminApplicationPermissions(HashMap<Permission, Set<String>> serviceDirectory) {
Set<PermissionInfo> permSet = Sets.newHashSet();
Collections.addAll(permSet, getDefaultPerms());
Collections.addAll(permSet, getAdminDefaultPerms());
permSet.addAll(serviceDirectory.keySet().stream().map(perm ->
new PermissionInfo(AppPermission.class.getName(), perm.name(), "")).collect(Collectors.toList()));
PermissionInfo[] permissionInfos = new PermissionInfo[permSet.size()];
return permSet.toArray(permissionInfos);
}
public static PermissionInfo[] getDefaultPerms() {
return new PermissionInfo[]{
new PermissionInfo(PackagePermission.class.getName(), "*", PackagePermission.EXPORTONLY),
new PermissionInfo(PackagePermission.class.getName(), "*", PackagePermission.IMPORT),
new PermissionInfo(AdaptPermission.class.getName(), "*", AdaptPermission.ADAPT),
};
}
public static PermissionInfo[] getAdminDefaultPerms() {
return new PermissionInfo[]{
new PermissionInfo(ServicePermission.class.getName(),
ApplicationAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
ClusterAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
MastershipAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
DeviceAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
HostAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LinkAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
DriverAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
StorageAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LabelResourceAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
TunnelAdminService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
ApplicationService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
ComponentConfigService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
CoreService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
ClusterService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LeadershipService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
MastershipService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
DeviceService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
DeviceClockService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
DriverService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
FlowRuleService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
FlowObjectiveService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
GroupService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
HostService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
HostClockService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
IntentService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
IntentClockService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
IntentExtensionService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
PartitionService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LinkService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LinkResourceService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
LabelResourceService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
PacketService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
ProxyArpService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
StatisticService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
PathService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
TopologyService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
TunnelService.class.getName(), ServicePermission.GET),
new PermissionInfo(ServicePermission.class.getName(),
StorageService.class.getName(), ServicePermission.GET),
};
}
public static HashMap<Permission, Set<String>> getServiceDirectory() {
HashMap<Permission, Set<String>> serviceDirectory = new FastHashMap();
serviceDirectory.put(Permission.APP_READ, ImmutableSet.of(
ApplicationService.class.getName(), CoreService.class.getName()));
serviceDirectory.put(Permission.APP_EVENT, ImmutableSet.of(
ApplicationService.class.getName(), CoreService.class.getName()));
serviceDirectory.put(Permission.CONFIG_READ, ImmutableSet.of(
ComponentConfigService.class.getName()));
serviceDirectory.put(Permission.CONFIG_WRITE, ImmutableSet.of(
ComponentConfigService.class.getName()));
serviceDirectory.put(Permission.CLUSTER_READ, ImmutableSet.of(
ClusterService.class.getName(), LeadershipService.class.getName(),
MastershipService.class.getName()));
serviceDirectory.put(Permission.CLUSTER_WRITE, ImmutableSet.of(
LeadershipService.class.getName(), MastershipService.class.getName()));
serviceDirectory.put(Permission.CLUSTER_EVENT, ImmutableSet.of(
ClusterService.class.getName(), LeadershipService.class.getName(),
MastershipService.class.getName()));
serviceDirectory.put(Permission.DEVICE_READ, ImmutableSet.of(
DeviceService.class.getName(), DeviceClockService.class.getName()));
serviceDirectory.put(Permission.DEVICE_EVENT, ImmutableSet.of(
DeviceService.class.getName()));
serviceDirectory.put(Permission.DRIVER_READ, ImmutableSet.of(
DriverService.class.getName()));
serviceDirectory.put(Permission.DRIVER_WRITE, ImmutableSet.of(
DriverService.class.getName()));
serviceDirectory.put(Permission.FLOWRULE_READ, ImmutableSet.of(
FlowRuleService.class.getName()));
serviceDirectory.put(Permission.FLOWRULE_WRITE, ImmutableSet.of(
FlowRuleService.class.getName(), FlowObjectiveService.class.getName()));
serviceDirectory.put(Permission.FLOWRULE_EVENT, ImmutableSet.of(
FlowRuleService.class.getName()));
serviceDirectory.put(Permission.GROUP_READ, ImmutableSet.of(
GroupService.class.getName()));
serviceDirectory.put(Permission.GROUP_WRITE, ImmutableSet.of(
GroupService.class.getName()));
serviceDirectory.put(Permission.GROUP_EVENT, ImmutableSet.of(
GroupService.class.getName()));
serviceDirectory.put(Permission.HOST_READ, ImmutableSet.of(
HostService.class.getName(), HostClockService.class.getName()));
serviceDirectory.put(Permission.HOST_WRITE, ImmutableSet.of(
HostService.class.getName()));
serviceDirectory.put(Permission.HOST_EVENT, ImmutableSet.of(
HostService.class.getName()));
serviceDirectory.put(Permission.INTENT_READ, ImmutableSet.of(
IntentService.class.getName(), PartitionService.class.getName(),
IntentClockService.class.getName()));
serviceDirectory.put(Permission.INTENT_WRITE, ImmutableSet.of(
IntentService.class.getName()));
serviceDirectory.put(Permission.INTENT_EVENT, ImmutableSet.of(
IntentService.class.getName()));
serviceDirectory.put(Permission.LINK_READ, ImmutableSet.of(
LinkService.class.getName(), LinkResourceService.class.getName(),
LabelResourceService.class.getName()));
serviceDirectory.put(Permission.LINK_WRITE, ImmutableSet.of(
LinkResourceService.class.getName(), LabelResourceService.class.getName()));
serviceDirectory.put(Permission.LINK_EVENT, ImmutableSet.of(
LinkService.class.getName(), LinkResourceService.class.getName(),
LabelResourceService.class.getName()));
serviceDirectory.put(Permission.PACKET_READ, ImmutableSet.of(
PacketService.class.getName(), ProxyArpService.class.getName()));
serviceDirectory.put(Permission.PACKET_WRITE, ImmutableSet.of(
PacketService.class.getName(), ProxyArpService.class.getName()));
serviceDirectory.put(Permission.PACKET_EVENT, ImmutableSet.of(
PacketService.class.getName()));
serviceDirectory.put(Permission.STATISTIC_READ, ImmutableSet.of(
StatisticService.class.getName()));
serviceDirectory.put(Permission.TOPOLOGY_READ, ImmutableSet.of(
TopologyService.class.getName(), PathService.class.getName()));
serviceDirectory.put(Permission.TOPOLOGY_EVENT, ImmutableSet.of(
TopologyService.class.getName()));
serviceDirectory.put(Permission.TUNNEL_READ, ImmutableSet.of(
TunnelService.class.getName()));
serviceDirectory.put(Permission.TUNNEL_WRITE, ImmutableSet.of(
TunnelService.class.getName()));
serviceDirectory.put(Permission.TUNNEL_EVENT, ImmutableSet.of(
TunnelService.class.getName()));
serviceDirectory.put(Permission.STORAGE_WRITE, ImmutableSet.of(
StorageService.class.getName()));
return serviceDirectory;
}
}
// public static PermissionInfo[] getNonAdminPerms() {
// return new PermissionInfo[]{
// new PermissionInfo(PackagePermission.class.getName(), "*", PackagePermission.EXPORTONLY),
// new PermissionInfo(PackagePermission.class.getName(), "*", PackagePermission.IMPORT),
// new PermissionInfo(AdaptPermission.class.getName(), "*", AdaptPermission.ADAPT),
// new PermissionInfo(ServicePermission.class.getName(),
// ApplicationService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// ComponentConfigService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// CoreService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// ClusterService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// LeadershipService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// MastershipService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// DeviceService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// DeviceClockService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// DriverService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// FlowRuleService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// FlowObjectiveService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// GroupService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// HostService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// HostClockService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// IntentService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// IntentClockService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// IntentExtensionService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// PartitionService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// LinkService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// LinkResourceService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// LabelResourceService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// PacketService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// ProxyArpService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// StatisticService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// PathService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// TopologyService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// TunnelService.class.getName(), ServicePermission.GET),
// new PermissionInfo(ServicePermission.class.getName(),
// StorageService.class.getName(), ServicePermission.GET),
// };
// }
\ No newline at end of file
package org.onosproject.security.impl;
import org.apache.commons.collections.FastHashMap;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.app.ApplicationEvent;
import org.onosproject.app.ApplicationListener;
import org.onosproject.app.ApplicationState;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.Permission;
import org.onosproject.security.util.AppPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.PackagePermission;
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.service.permissionadmin.PermissionInfo;
import java.security.AccessControlException;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.osgi.service.permissionadmin.PermissionAdmin;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Security-Mode ONOS management implementation.
*/
//TODO : implement a dedicated distributed store for SM-ONOS
@Component(immediate = true)
public class SecurityModeManager {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ApplicationAdminService appAdminService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FeaturesService featuresService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LogReaderService logReaderService;
private final Logger log = getLogger(getClass());
private SecurityBundleListener securityBundleListener = new SecurityBundleListener();
private SecurityApplicationListener securityApplicationListener = new SecurityApplicationListener();
private SecurityLogListener securityLogListener = new SecurityLogListener();
private Bundle bundle = null;
private BundleContext bundleContext = null;
private PermissionAdmin permissionAdmin = null;
private HashMap<String, ApplicationId> appTracker = null;
private HashMap<Permission, Set<String>> serviceDirectory = null;
@Activate
public void activate() {
if (System.getSecurityManager() == null) {
log.warn("J2EE security manager is disabled.");
deactivate();
return;
}
bundle = FrameworkUtil.getBundle(this.getClass());
bundleContext = bundle.getBundleContext();
bundleContext.addBundleListener(securityBundleListener);
appAdminService.addListener(securityApplicationListener);
logReaderService.addLogListener(securityLogListener);
appTracker = new FastHashMap();
permissionAdmin = getPermissionAdmin(bundleContext);
if (permissionAdmin == null) {
log.warn("Permission Admin not found.");
this.deactivate();
return;
}
serviceDirectory = PolicyBuilder.getServiceDirectory();
PermissionInfo[] allPerm = {
new PermissionInfo(AllPermission.class.getName(), "", ""), };
permissionAdmin.setPermissions(bundle.getLocation(), allPerm);
log.warn("Security-Mode Started");
}
@Deactivate
public void deactivate() {
bundleContext.removeBundleListener(securityBundleListener);
appAdminService.removeListener(securityApplicationListener);
logReaderService.removeLogListener(securityLogListener);
log.info("Stopped");
}
private class SecurityApplicationListener implements ApplicationListener {
@Override
public void event(ApplicationEvent event) {
//App needs to be restarted
if (event.type() == ApplicationEvent.Type.APP_PERMISSIONS_CHANGED) {
if (appAdminService.getState(event.subject().id()) == ApplicationState.ACTIVE) {
appAdminService.deactivate(event.subject().id());
print("Permissions updated (%s). Deactivating...",
event.subject().id().name());
}
}
}
}
private class SecurityBundleListener implements BundleListener {
@Override
public void bundleChanged(BundleEvent event) {
switch (event.getType()) {
case BundleEvent.INSTALLED:
setPermissions(event);
break;
case BundleEvent.UNINSTALLED:
clearPermissions(event);
break;
default:
break;
}
}
}
private void clearPermissions(BundleEvent bundleEvent) {
if (appTracker.containsKey(bundleEvent.getBundle().getLocation())) {
permissionAdmin.setPermissions(bundleEvent.getBundle().getLocation(), new PermissionInfo[]{});
appTracker.remove(bundleEvent.getBundle().getLocation());
}
}
// find the location of the installed bundle and enforce policy
private void setPermissions(BundleEvent bundleEvent) {
for (Application app : appAdminService.getApplications()) {
if (getBundleLocations(app).contains(bundleEvent.getBundle().getLocation())) {
String location = bundleEvent.getBundle().getLocation();
Set<org.onosproject.core.Permission> permissions =
appAdminService.getPermissions(app.id());
//Permissions granted by user overrides the permissions specified in App.Xml file
if (permissions == null) {
permissions = app.permissions();
}
if (permissions.isEmpty()) {
print("Application %s has not been granted any permission.", app.id().name());
}
PermissionInfo[] perms = null;
switch (app.role()) {
case ADMIN:
perms = PolicyBuilder.getAdminApplicationPermissions(serviceDirectory);
break;
case REGULAR:
perms = PolicyBuilder.getApplicationPermissions(serviceDirectory, permissions);
break;
case UNSPECIFIED:
default:
//no role has been assigned.
perms = PolicyBuilder.getDefaultPerms();
log.warn("Application %s has no role assigned.", app.id().name());
break;
}
permissionAdmin.setPermissions(location, perms);
appTracker.put(location, app.id());
break;
}
}
}
//TODO: dispatch security policy violation event via distributed store
//immediately notify and deactivate the application upon policy violation
private class SecurityLogListener implements LogListener {
@Override
public void logged(LogEntry entry) {
if (entry != null) {
if (entry.getException() != null) {
ApplicationId applicationId = appTracker.get(entry.getBundle().getLocation());
if (applicationId != null) {
if (appAdminService.getState(applicationId).equals(ApplicationState.ACTIVE)) {
if (entry.getException() instanceof AccessControlException) {
java.security.Permission permission =
((AccessControlException) entry.getException()).getPermission();
handleException(applicationId.name(), permission);
appAdminService.deactivate(applicationId);
}
}
}
}
}
}
}
private void handleException(String name, java.security.Permission perm) {
if (perm instanceof ServicePermission || perm instanceof PackagePermission) {
print("%s has attempted to %s %s.", name, perm.getActions(), perm.getName());
} else if (perm instanceof AppPermission) {
print("%s has attempted to call an NB API that requires %s permission.",
name, perm.getName().toUpperCase());
} else {
print("%s has attempted to perform an action that requires %s", name, perm.toString());
}
print("POLICY VIOLATION: Deactivating %s.", name);
}
private void print(String format, Object... args) {
System.out.println(String.format("SM-ONOS: " + format, args));
log.warn(String.format(format, args));
}
private List<String> getBundleLocations(Application app) {
List<String> locations = new ArrayList();
for (String name : app.features()) {
try {
Feature feature = featuresService.getFeature(name);
locations.addAll(
feature.getBundles().stream().map(BundleInfo::getLocation).collect(Collectors.toList()));
} catch (Exception e) {
return locations;
}
}
return locations;
}
private PermissionAdmin getPermissionAdmin(BundleContext context) {
return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName()));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>onos-core</artifactId>
<groupId>org.onosproject</groupId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-security</artifactId>
<packaging>pom</packaging>
<modules>
<module>util</module>
<module>impl</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>onos-security</artifactId>
<groupId>org.onosproject</groupId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>onos-security-util</artifactId>
<packaging>bundle</packaging>
</project>
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.security.util;
/**
* Checks if the caller has the required permission to call each API.
*/
public final class AppGuard {
private AppGuard() {
}
public static boolean check(String perm) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
System.getSecurityManager().checkPermission(new AppPermission(perm));
}
return true;
}
}
/*
* Copyright 2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.security.util;
import java.security.BasicPermission;
/**
* Implementation of API access permission.
*/
public class AppPermission extends BasicPermission {
public AppPermission(String name) {
super(name.toUpperCase(), "");
}
public AppPermission(String name, String actions) {
super(name.toUpperCase(), actions);
}
}
......@@ -123,6 +123,13 @@
<bundle>mvn:org.onosproject/onos-cli/@ONOS-VERSION</bundle>
</feature>
<feature name="onos-security" version="@FEATURE-VERSION"
description="Security-Mode ONOS">
<!--<bundle>mvn:org.onosproject/onos-security-felix/2.2.0-ONOS</bundle>-->
<bundle>mvn:org.onosproject/onos-security-impl/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-security-util/@ONOS-VERSION</bundle>
</feature>
<!-- Deprecated! For standalone testing only. -->
<feature name="onos-core-trivial" version="@FEATURE-VERSION"
description="ONOS trivial core components">
......