From 1ac48bc36cff85f9c1a630628698331f7a2356dd Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:27:15 -0800 Subject: [PATCH 1/8] RoleType: public enum to get presently defined static role in CloudStack Signed-off-by: Rohit Yadav --- .../org/apache/cloudstack/acl/RoleType.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 api/src/org/apache/cloudstack/acl/RoleType.java diff --git a/api/src/org/apache/cloudstack/acl/RoleType.java b/api/src/org/apache/cloudstack/acl/RoleType.java new file mode 100644 index 00000000000..0d1c4460c1e --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/RoleType.java @@ -0,0 +1,37 @@ +// 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 org.apache.cloudstack.acl; + +// Enum for default roles in CloudStack +public enum RoleType { + + Admin(1), + ResourceAdmin(2), + DomainAdmin(4), + User(8), + Unknown(0); + + private int mask; + + private RoleType(int mask) { + this.mask = mask; + } + + public int getValue() { + return mask; + } +} From f2ae0ae5ae70fbb5f33c004e05e4a17327094651 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:29:01 -0800 Subject: [PATCH 2/8] PropertiesUtil: Refactor process config file method in utils, return map of key=value Signed-off-by: Rohit Yadav --- utils/src/com/cloud/utils/PropertiesUtil.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/utils/src/com/cloud/utils/PropertiesUtil.java b/utils/src/com/cloud/utils/PropertiesUtil.java index 3909ca876b6..90f8af8b33f 100755 --- a/utils/src/com/cloud/utils/PropertiesUtil.java +++ b/utils/src/com/cloud/utils/PropertiesUtil.java @@ -17,6 +17,8 @@ package com.cloud.utils; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -28,6 +30,7 @@ import java.util.Set; import org.apache.log4j.Logger; public class PropertiesUtil { + private static final Logger s_logger = Logger.getLogger(PropertiesUtil.class); /** * Searches the class path and local paths to find the config file. * @param path path to find. if it starts with / then it's absolute path. @@ -116,4 +119,41 @@ public class PropertiesUtil { } return null; } + + // Returns key=value pairs by parsing a commands.properties/config file + // with syntax; key=cmd;value (with this syntax cmd is stripped) and key=value + public static Map processConfigFile(String[] configFiles) { + Map configMap = new HashMap(); + Properties preProcessedCommands = new Properties(); + for (String configFile : configFiles) { + File commandsFile = findConfigFile(configFile); + if (commandsFile != null) { + try { + preProcessedCommands.load(new FileInputStream(commandsFile)); + } catch (FileNotFoundException fnfex) { + // in case of a file within a jar in classpath, try to open stream using url + InputStream stream = PropertiesUtil.openStreamFromURL(configFile); + if (stream != null) { + try { + preProcessedCommands.load(stream); + } catch (IOException e) { + s_logger.error("IO Exception, unable to find properties file:", fnfex); + } + } else { + s_logger.error("Unable to find properites file", fnfex); + } + } catch (IOException ioe) { + s_logger.error("IO Exception loading properties file", ioe); + } + } + } + + for (Object key : preProcessedCommands.keySet()) { + String preProcessedCommand = preProcessedCommands.getProperty((String) key); + int splitIndex = preProcessedCommand.lastIndexOf(";"); + String value = preProcessedCommand.substring(splitIndex+1); + configMap.put((String)key, value); + } + return configMap; + } } From 1425736c193c56a51ec59b23e35080bd74926baf Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:31:32 -0800 Subject: [PATCH 3/8] AccountManager: Add method to translate account type to role type Signed-off-by: Rohit Yadav --- api/src/com/cloud/user/AccountService.java | 3 +++ .../com/cloud/user/AccountManagerImpl.java | 26 +++++++++++++++++++ .../cloud/user/MockAccountManagerImpl.java | 6 +++++ 3 files changed, 35 insertions(+) diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index ce16f5ee063..9f5f4d225e0 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; @@ -193,6 +194,8 @@ public interface AccountService { UserAccount getUserByApiKey(String apiKey); + RoleType getRoleType(Account account); + void checkAccess(Account account, Domain domain) throws PermissionDeniedException; void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException; diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index c6a7d51f08d..b910a03f99b 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -37,6 +37,7 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; @@ -1542,6 +1543,31 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } + @Override + public RoleType getRoleType(Account account) { + RoleType roleType = RoleType.Unknown; + if (account == null) + return roleType; + short accountType = account.getType(); + + // Account type to role type translation + switch (accountType) { + case Account.ACCOUNT_TYPE_ADMIN: + roleType = RoleType.Admin; + break; + case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: + roleType = RoleType.DomainAdmin; + break; + case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: + roleType = RoleType.ResourceAdmin; + break; + case Account.ACCOUNT_TYPE_NORMAL: + roleType = RoleType.User; + break; + } + return roleType; + } + @Override public User getActiveUser(long userId) { return _userDao.findById(userId); diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index ae5d0e5de4b..550304adfff 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -23,6 +23,7 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.api.query.vo.ControlledViewEntity; @@ -344,4 +345,9 @@ public class MockAccountManagerImpl implements Manager, AccountManager, AccountS return null; } + @Override + public RoleType getRoleType(Account account) { + return null; + } + } From a56f355cebc4b409840a3f2c2deea5bd0f91ab49 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:33:52 -0800 Subject: [PATCH 4/8] ApiServer: get role type from account manager using account Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 29 +++---------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 1c1e8ca0e96..73871259504 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -790,37 +790,14 @@ public class ApiServer implements HttpRequestHandler { return true; } - private boolean isCommandAvailable(User user, String commandName) { + private boolean isCommandAvailable(User user, String commandName) + throws PermissionDeniedException { if (user == null) { return false; } Account account = _accountMgr.getAccount(user.getAccountId()); - if (account == null) { - return false; - } - - RoleType roleType = RoleType.Unknown; - short accountType = account.getType(); - - // Account type to role type translation - switch (accountType) { - case Account.ACCOUNT_TYPE_ADMIN: - roleType = RoleType.Admin; - break; - case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: - roleType = RoleType.DomainAdmin; - break; - case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: - roleType = RoleType.ResourceAdmin; - break; - case Account.ACCOUNT_TYPE_NORMAL: - roleType = RoleType.User; - break; - default: - return false; - } - + RoleType roleType = _accountMgr.getRoleType(account); for (APIAccessChecker apiChecker : _apiAccessCheckers) { // Fail the checking if any checker fails to verify if (!apiChecker.canAccessAPI(roleType, commandName)) From c4e890c55d4b106934ff3588adfbbf5a12f48d1e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:43:44 -0800 Subject: [PATCH 5/8] PluggableService: Refactor method to return map of key value pairs - Makes plugins self contained so they decide their properties file format - PluggableService creates the contract that implementing entity will return a properties map which is apiname:rolemask (both are strings) Signed-off-by: Rohit Yadav --- .../server/ManagementServerSimulatorImpl.java | 18 +++++++++--------- .../network/element/CiscoNexusVSMElement.java | 7 +++++-- .../element/F5ExternalLoadBalancerElement.java | 7 +++++-- .../JuniperSRXExternalFirewallElement.java | 7 +++++-- .../network/element/NetscalerElement.java | 6 ++++-- .../network/element/NiciraNvpElement.java | 6 ++++-- .../network/element/VirtualRouterElement.java | 6 ++++-- .../cloud/server/ManagementServerExtImpl.java | 6 ++++-- .../com/cloud/server/ManagementServerImpl.java | 5 +++-- .../utils/component/PluggableService.java | 4 +++- 10 files changed, 46 insertions(+), 26 deletions(-) diff --git a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java index ad42c23380e..44ab26a020a 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java @@ -17,16 +17,16 @@ package com.cloud.server; +import com.cloud.utils.PropertiesUtil; + +import java.util.Map; + public class ManagementServerSimulatorImpl extends ManagementServerExtImpl { @Override - public String[] getPropertiesFiles() { - String[] apis = super.getPropertiesFiles(); - String[] newapis = new String[apis.length + 1]; - for (int i = 0; i < apis.length; i++) { - newapis[i] = apis[i]; - } - - newapis[apis.length] = "commands-simulator.properties"; - return newapis; + public Map getProperties() { + Map apiNameRoleMaskMapping = super.getProperties(); + apiNameRoleMaskMapping.putAll(PropertiesUtil.processConfigFile(new String[] + {"commands-simulator.properties"})); + return apiNameRoleMaskMapping; } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java index 911078eac50..2cf87877859 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -17,6 +17,7 @@ package com.cloud.network.element; +import java.lang.String; import java.util.List; import java.util.Map; import java.util.ArrayList; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.commands.DeleteCiscoNexusVSMCmd; @@ -237,7 +239,8 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme } @Override - public String[] getPropertiesFiles() { - return new String[] { "cisconexusvsm_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "cisconexusvsm_commands.properties" }); } } diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 335dc6ecfec..438498ff38c 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -260,8 +262,9 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan } @Override - public String[] getPropertiesFiles() { - return new String[] { "f5bigip_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "f5bigip_commands.properties" }); } @Override diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index f491e66925a..55722ae23ab 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -402,8 +404,9 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan } @Override - public String[] getPropertiesFiles() { - return new String[] { "junipersrx_commands.properties"}; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "junipersrx_commands.properties"}); } @Override diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index b1fe949632c..ac1619ef1f8 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -464,8 +465,9 @@ StaticNatServiceProvider { } @Override - public String[] getPropertiesFiles() { - return new String[] { "netscalerloadbalancer_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "netscalerloadbalancer_commands.properties" }); } @Override diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index cc53ee1afae..22fab500fdb 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -27,6 +27,7 @@ import java.util.UUID; import javax.ejb.Local; import javax.naming.ConfigurationException; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -540,8 +541,9 @@ public class NiciraNvpElement extends AdapterBase implements } @Override - public String[] getPropertiesFiles() { - return new String[] { "nicira-nvp_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "nicira-nvp_commands.properties" }); } @Override diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index b5b8b1a73cd..823b74f269b 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -24,6 +24,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.cloudstack.api.command.admin.router.ConfigureVirtualRouterElementCmd; import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; import org.apache.log4j.Logger; @@ -680,8 +681,9 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public String[] getPropertiesFiles() { - return new String[] { "virtualrouter_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "virtualrouter_commands.properties" }); } @Override diff --git a/server/src/com/cloud/server/ManagementServerExtImpl.java b/server/src/com/cloud/server/ManagementServerExtImpl.java index b7320276341..8a59d2f9c1c 100644 --- a/server/src/com/cloud/server/ManagementServerExtImpl.java +++ b/server/src/com/cloud/server/ManagementServerExtImpl.java @@ -29,6 +29,7 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.projects.Project; +import com.cloud.utils.PropertiesUtil; import org.apache.cloudstack.api.response.UsageTypeResponse; import com.cloud.usage.UsageJobVO; import com.cloud.usage.UsageTypes; @@ -206,8 +207,9 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man } @Override - public String[] getPropertiesFiles() { - return new String[] { "commands.properties", "commands-ext.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "commands.properties", "commands-ext.properties" }); } private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index dcecaf40a57..3e0f6efae7c 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2297,8 +2297,9 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public String[] getPropertiesFiles() { - return new String[] { "commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "commands.properties" }); } protected class EventPurgeTask implements Runnable { diff --git a/utils/src/com/cloud/utils/component/PluggableService.java b/utils/src/com/cloud/utils/component/PluggableService.java index d2199394a69..f6f72a904d0 100644 --- a/utils/src/com/cloud/utils/component/PluggableService.java +++ b/utils/src/com/cloud/utils/component/PluggableService.java @@ -16,9 +16,11 @@ // under the License. package com.cloud.utils.component; +import java.util.Map; + // This interface defines methods for pluggable code within the Cloud Stack. public interface PluggableService { // The config command properties filenames that lists allowed API commands // and role masks supported by this pluggable service - String[] getPropertiesFiles(); + Map getProperties(); } From 0b1c2a5981fea3d4455acee6ac77e9fa84c9724b Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:47:59 -0800 Subject: [PATCH 6/8] ApiDiscovery: Fix listApis interface, fix getProperties In case of api discovery, it does not make sense to create a separate properties file If this plugin is enabled in components.xml, a user should be able to discover all the apis accessible to their role. listApis based on role type of caller user Signed-off-by: Rohit Yadav --- .../api/command/user/discovery/ListApisCmd.java | 7 ++++++- .../cloudstack/discovery/ApiDiscoveryService.java | 3 ++- .../cloudstack/discovery/ApiDiscoveryServiceImpl.java | 10 +++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index dcbaec1d160..feab20ac5cf 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,6 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; @@ -39,7 +42,9 @@ public class ListApisCmd extends BaseListCmd { @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - ListResponse response = (ListResponse) _apiDiscoveryService.listApis(); + Account caller = UserContext.current().getCaller(); + RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller()); + ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType); if (response == null) { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find and process any apis"); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index 96ea3ee4d34..a1d440e9ccf 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -17,9 +17,10 @@ package org.apache.cloudstack.discovery; import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; public interface ApiDiscoveryService extends PluggableService { - ListResponse listApis(); + ListResponse listApis(RoleType roleType); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java index ea6b206fa44..2bc17bdbf4d 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -16,7 +16,9 @@ // under the License. package org.apache.cloudstack.discovery; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.ReflectUtil; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -108,12 +110,14 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } @Override - public ListResponse listApis() { + public ListResponse listApis(RoleType roleType) { return _discoveryResponse; } @Override - public String[] getPropertiesFiles() { - return new String[] { "api-discovery_commands.properties" }; + public Map getProperties() { + Map apiDiscoveryPropertyMap = new HashMap(); + apiDiscoveryPropertyMap.put("listApis", "15"); + return apiDiscoveryPropertyMap; } } From 8f26e171e64726a726fa146f9c02433e48c0ba60 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:51:46 -0800 Subject: [PATCH 7/8] ManagementServerImpl: Fix missing import of PropertiesUtil Signed-off-by: Rohit Yadav --- server/src/com/cloud/server/ManagementServerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 3e0f6efae7c..79ad759dd0b 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -223,6 +223,7 @@ import com.cloud.utils.EnumUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.Ternary; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; From 345c179e77dce7ba471f6846fac785bd34bda294 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:53:18 -0800 Subject: [PATCH 8/8] plugins: Check access based on roleType, remove unnecessary properties.in file - Fix StaticRoleBasedAPIAccessChecker to check api access based on roletype - Remove properties file which is not needed now for api discovery plugin Signed-off-by: Rohit Yadav --- .../api-discovery_commands.properties.in | 23 --- .../acl/StaticRoleBasedAPIAccessChecker.java | 136 +++++++----------- 2 files changed, 48 insertions(+), 111 deletions(-) delete mode 100644 client/tomcatconf/api-discovery_commands.properties.in diff --git a/client/tomcatconf/api-discovery_commands.properties.in b/client/tomcatconf/api-discovery_commands.properties.in deleted file mode 100644 index 49ddfde42d8..00000000000 --- a/client/tomcatconf/api-discovery_commands.properties.in +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -# bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = -# RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -# Please standardize naming conventions to camel-case (even for acronyms). - -# CloudStack API Discovery service command -listApis=15 diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 43ca403f890..689540aa291 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -16,28 +16,23 @@ // under the License. package org.apache.cloudstack.acl; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.APIAccessChecker; -import org.apache.cloudstack.acl.RoleType; -import static org.apache.cloudstack.acl.RoleType.*; -import org.apache.log4j.Logger; - import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; -import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.PluggableService; +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.cloudstack.acl.RoleType.*; +import org.apache.log4j.Logger; + // This is the default API access checker that grab's the user's account // based on the account type, access is granted @Local(value=APIAccessChecker.class) @@ -60,35 +55,29 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA } @Override - public boolean canAccessAPI(RoleType roleType, String apiCommandName) - throws PermissionDeniedException{ + public boolean canAccessAPI(RoleType roleType, String commandName) + throws PermissionDeniedException { - boolean commandExists = s_allCommands.contains(apiCommandName); + boolean commandExists = s_allCommands.contains(commandName); + boolean commandAccessible = false; - if(commandExists) { - return isCommandAvailableForAccount(roleType, apiCommandName); + if (commandExists) { + switch (roleType) { + case Admin: + commandAccessible = s_adminCommands.contains(commandName); + break; + case DomainAdmin: + commandAccessible = s_resellerCommands.contains(commandName); + break; + case ResourceAdmin: + commandAccessible = s_resourceDomainAdminCommands.contains(commandName); + break; + case User: + commandAccessible = s_userCommands.contains(commandName); + break; + } } - - return commandExists; - } - - private static boolean isCommandAvailableForAccount(RoleType roleType, String commandName) { - boolean isCommandAvailable = false; - switch (roleType) { - case Admin: - isCommandAvailable = s_adminCommands.contains(commandName); - break; - case DomainAdmin: - isCommandAvailable = s_resellerCommands.contains(commandName); - break; - case ResourceAdmin: - isCommandAvailable = s_resourceDomainAdminCommands.contains(commandName); - break; - case User: - isCommandAvailable = s_userCommands.contains(commandName); - break; - } - return isCommandAvailable; + return commandExists && commandAccessible; } @Override @@ -100,69 +89,40 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA List services = locator.getAllPluggableServices(); services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); - List configFiles = new ArrayList(); + Map configPropertiesMap = new HashMap(); for (PluggableService service : services) { - configFiles.addAll(Arrays.asList(service.getPropertiesFiles())); + configPropertiesMap.putAll(service.getProperties()); } - processConfigFiles(configFiles); + processConfigFiles(configPropertiesMap); return true; } - private void processConfigFiles(List configFiles) { - Properties preProcessedCommands = new Properties(); - - for (String configFile : configFiles) { - File commandsFile = PropertiesUtil.findConfigFile(configFile); - if (commandsFile != null) { - try { - preProcessedCommands.load(new FileInputStream(commandsFile)); - } catch (FileNotFoundException fnfex) { - // in case of a file within a jar in classpath, try to open stream using url - InputStream stream = PropertiesUtil.openStreamFromURL(configFile); - if (stream != null) { - try { - preProcessedCommands.load(stream); - } catch (IOException e) { - s_logger.error("IO Exception, unable to find properties file:", fnfex); - } - } else { - s_logger.error("Unable to find properites file", fnfex); - } - } catch (IOException ioe) { - s_logger.error("IO Exception loading properties file", ioe); - } - } - } - - for (Object key : preProcessedCommands.keySet()) { - String preProcessedCommand = preProcessedCommands.getProperty((String) key); - int splitIndex = preProcessedCommand.lastIndexOf(";"); - // Backward compatible to old style, apiname=pkg;mask - String mask = preProcessedCommand.substring(splitIndex+1); - + private void processConfigFiles(Map config) { + for (Map.Entry entry: config.entrySet()) { + String apiName = entry.getKey(); + String roleMask = entry.getValue(); try { - short cmdPermissions = Short.parseShort(mask); + short cmdPermissions = Short.parseShort(roleMask); if ((cmdPermissions & Admin.getValue()) != 0) { - s_adminCommands.add((String) key); + s_adminCommands.add(apiName); } if ((cmdPermissions & ResourceAdmin.getValue()) != 0) { - s_resourceDomainAdminCommands.add((String) key); + s_resourceDomainAdminCommands.add(apiName); } if ((cmdPermissions & DomainAdmin.getValue()) != 0) { - s_resellerCommands.add((String) key); + s_resellerCommands.add(apiName); } if ((cmdPermissions & User.getValue()) != 0) { - s_userCommands.add((String) key); + s_userCommands.add(apiName); } - s_allCommands.addAll(s_adminCommands); - s_allCommands.addAll(s_resourceDomainAdminCommands); - s_allCommands.addAll(s_userCommands); - s_allCommands.addAll(s_resellerCommands); } catch (NumberFormatException nfe) { - s_logger.info("Malformed command.properties permissions value, key = " + key + ", value = " + preProcessedCommand); + s_logger.info("Malformed commands.properties permissions value, for entry: " + entry.toString()); } } + s_allCommands.addAll(s_adminCommands); + s_allCommands.addAll(s_resourceDomainAdminCommands); + s_allCommands.addAll(s_userCommands); + s_allCommands.addAll(s_resellerCommands); } - }