diff --git a/api/src/main/java/com/cloud/exception/UnavailableCommandException.java b/api/src/main/java/com/cloud/exception/UnavailableCommandException.java new file mode 100644 index 00000000000..d5b7faa8f36 --- /dev/null +++ b/api/src/main/java/com/cloud/exception/UnavailableCommandException.java @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.exception; + +import com.cloud.utils.SerialVersionUID; + +public class UnavailableCommandException extends PermissionDeniedException { + + private static final long serialVersionUID = SerialVersionUID.UnavailableCommandException; + + protected UnavailableCommandException() { + super(); + } + + public UnavailableCommandException(String msg) { + super(msg); + } + + public UnavailableCommandException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java index 3dfdb01b2e5..d10c191151f 100644 --- a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java +++ b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.exception.UnavailableCommandException; import org.apache.cloudstack.api.APICommand; import com.cloud.exception.PermissionDeniedException; @@ -53,8 +54,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API } private void denyApiAccess(final String commandName) throws PermissionDeniedException { - throw new PermissionDeniedException("The API does not exist or is blacklisted for the account's role. " + - "The account with is not allowed to request the api: " + commandName); + throw new PermissionDeniedException("The API " + commandName + " is blacklisted for the account's role."); } public boolean isDisabled() { @@ -99,8 +99,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API } // Default deny all - denyApiAccess(commandName); - return false; + throw new UnavailableCommandException("The API " + commandName + " does not exist or is not available for this account."); } public void addApiToRoleBasedAnnotationsMap(final RoleType roleType, final String commandName) { diff --git a/plugins/acl/static-role-based/src/main/java/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/main/java/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index f3dc3a3b8d7..4a33a0876c3 100644 --- a/plugins/acl/static-role-based/src/main/java/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/main/java/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.exception.UnavailableCommandException; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -45,6 +46,7 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC protected static final Logger LOGGER = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); private Set commandPropertyFiles = new HashSet(); + private Set commandNames = new HashSet(); private Set commandsPropertiesOverrides = new HashSet(); private Map> commandsPropertiesRoleBasedApisMap = new HashMap>(); private Map> annotationRoleBasedApisMap = new HashMap>(); @@ -87,7 +89,11 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC return true; } - throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); + if (commandNames.contains(commandName)) { + throw new PermissionDeniedException("The API is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); + } else { + throw new UnavailableCommandException("The API " + commandName + " does not exist or is not available for this account."); + } } @Override @@ -110,6 +116,9 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC if (!commands.contains(command.name())) commands.add(command.name()); } + if (!commandNames.contains(command.name())) { + commandNames.add(command.name()); + } } } return super.start(); @@ -119,6 +128,9 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC for (Map.Entry entry : configMap.entrySet()) { String apiName = entry.getKey(); String roleMask = entry.getValue(); + if (!commandNames.contains(apiName)) { + commandNames.add(apiName); + } commandsPropertiesOverrides.add(apiName); try { short cmdPermissions = Short.parseShort(roleMask); diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index c0944446735..13d31f4ee3f 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -1163,8 +1163,7 @@ def addFWFramework(brname): execute("sysctl -w net.bridge.bridge-nf-call-iptables=1") execute("sysctl -w net.bridge.bridge-nf-call-ip6tables=1") except: - logging.debug("failed to turn on bridge netfilter") - return False + logging.warn("failed to turn on bridge netfilter") brfw = getBrfw(brname) try: diff --git a/server/src/main/java/com/cloud/api/ApiServer.java b/server/src/main/java/com/cloud/api/ApiServer.java index 6411fe07367..a97984a2be2 100644 --- a/server/src/main/java/com/cloud/api/ApiServer.java +++ b/server/src/main/java/com/cloud/api/ApiServer.java @@ -34,6 +34,7 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.RequestLimitException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.UnavailableCommandException; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.DomainManager; @@ -958,6 +959,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } catch (final RequestLimitException ex) { s_logger.debug(ex.getMessage()); throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage()); + } catch (final UnavailableCommandException ex) { + s_logger.debug(ex.getMessage()); + throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, ex.getMessage()); } catch (final PermissionDeniedException ex) { final String errorMessage = "The given command '" + commandName + "' either does not exist, is not available" + " for user, or not available from ip address '" + remoteAddress + "'."; diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index dfd5916892f..f84afdb4529 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -521,9 +521,9 @@ class TestRouterServices(cloudstackTestCase): ) if str(result[3]) == "min,": self.assertEqual( - (int(result[2]) < 3), + (int(result[2]) < 20), True, - "Check uptime is less than 3 mins or not" + "Check uptime is less than 20 mins or not" ) else: self.assertEqual( diff --git a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java index 4dd5add28dd..413ca1a417f 100644 --- a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java +++ b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java @@ -68,4 +68,5 @@ public interface SerialVersionUID { public static final long NioConnectionException = Base | 0x2c; public static final long TaskExecutionException = Base | 0x2d; public static final long SnapshotBackupException = Base | 0x2e; + public static final long UnavailableCommandException = Base | 0x2f; }