[ 
https://issues.apache.org/jira/browse/CLOUDSTACK-8562?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15250174#comment-15250174
 ] 

ASF GitHub Bot commented on CLOUDSTACK-8562:
--------------------------------------------

Github user bhaisaab commented on a diff in the pull request:

    https://github.com/apache/cloudstack/pull/1489#discussion_r60440106
  
    --- Diff: 
plugins/acl/dynamic-role-based/src/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java
 ---
    @@ -0,0 +1,170 @@
    +// 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;
    +
    +import com.cloud.exception.InvalidParameterValueException;
    +import com.cloud.exception.PermissionDeniedException;
    +import com.cloud.user.Account;
    +import com.cloud.user.AccountService;
    +import com.cloud.user.User;
    +import com.cloud.utils.component.AdapterBase;
    +import com.cloud.utils.component.PluggableService;
    +import com.google.common.base.Strings;
    +import org.apache.cloudstack.api.APICommand;
    +
    +import org.apache.log4j.Logger;
    +
    +import javax.ejb.Local;
    +import javax.inject.Inject;
    +import javax.naming.ConfigurationException;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Set;
    +
    +@Local(value = APIChecker.class)
    +public class DynamicRoleBasedAPIAccessChecker extends AdapterBase 
implements APIChecker {
    +
    +    protected static final Logger LOGGER = 
Logger.getLogger(DynamicRoleBasedAPIAccessChecker.class);
    +
    +    @Inject
    +    private AccountService accountService;
    +    @Inject
    +    private RoleService roleService;
    +
    +    private List<PluggableService> services;
    +    private Map<RoleType, Set<String>> annotationRoleBasedApisMap = new 
HashMap<>();
    +
    +    protected DynamicRoleBasedAPIAccessChecker() {
    +        super();
    +        for (RoleType roleType : RoleType.values()) {
    +            annotationRoleBasedApisMap.put(roleType, new 
HashSet<String>());
    +        }
    +    }
    +
    +    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);
    +    }
    +
    +    private boolean checkPermission(final List <? extends RolePermission> 
permissions, final RolePermission.Permission permissionToCheck, final String 
commandName) {
    +        if (permissions == null || permissions.isEmpty() || 
Strings.isNullOrEmpty(commandName)) {
    +            return false;
    +        }
    +        for (final RolePermission permission : permissions) {
    +            if (permission.getPermission() != permissionToCheck) {
    +                continue;
    +            }
    +            try {
    +                final Rule rule = new Rule(permission.getRule());
    +                if (rule.matches(commandName)) {
    +                    return true;
    +                }
    +            } catch (InvalidParameterValueException e) {
    +                LOGGER.warn("Invalid rule permission, please fix id=" + 
permission.getId() + " rule=" + permission.getRule());
    +                continue;
    +            }
    +        }
    +        return false;
    +    }
    +
    +    public boolean isDisabled() {
    +        return !roleService.isEnabled();
    +    }
    +
    +    @Override
    +    public boolean checkAccess(User user, String commandName) throws 
PermissionDeniedException {
    +        if (isDisabled()) {
    +            return true;
    +        }
    +        Account account = accountService.getAccount(user.getAccountId());
    +        if (account == null) {
    +            throw new PermissionDeniedException("The account id=" + 
user.getAccountId() + "for user id=" + user.getId() + "is null");
    +        }
    +
    +        final Role accountRole = roleService.findRole(account.getRoleId());
    +        if (accountRole == null || accountRole.getId() < 1L) {
    +            denyApiAccess(commandName);
    +        }
    +
    +        // Allow all APIs for root admins
    +        if (accountRole.getRoleType() == RoleType.Admin && 
accountRole.getId() == RoleType.Admin.getId()) {
    +            return true;
    +        }
    +
    +        final List<RolePermission> rolePermissions = 
roleService.findAllPermissionsBy(accountRole.getId());
    +
    +        // Check for allow rules
    +        if (checkPermission(rolePermissions, 
RolePermission.Permission.ALLOW, commandName)) {
    +            return true;
    +        }
    +
    +        // Check for deny rules
    +        if (checkPermission(rolePermissions, 
RolePermission.Permission.DENY, commandName)) {
    +            denyApiAccess(commandName);
    +        }
    +
    +        // Check annotations
    +        if (annotationRoleBasedApisMap.get(accountRole.getRoleType()) != 
null
    +                && 
annotationRoleBasedApisMap.get(accountRole.getRoleType()).contains(commandName))
 {
    +            return true;
    +        }
    +
    +        denyApiAccess(commandName);
    +        return false;
    +    }
    +
    +    public void addApiToRoleBasedAnnotationsMap(final RoleType roleType, 
final String commandName) {
    +        if (roleType == null || Strings.isNullOrEmpty(commandName)) {
    +            return;
    +        }
    +        final Set<String> commands = 
annotationRoleBasedApisMap.get(roleType);
    +        if (commands != null && !commands.contains(commandName)) {
    +            commands.add(commandName);
    --- End diff --
    
    @koushik-das (3) from step 2, this methods populates an internal map that 
is a list of authorized apis for a given role types; we've only 4 role types 
used across cloudstack (and also in commands.properties aka the static checker) 
namely admin, resource admin, domain admin and user


> User Definable Roles
> --------------------
>
>                 Key: CLOUDSTACK-8562
>                 URL: https://issues.apache.org/jira/browse/CLOUDSTACK-8562
>             Project: CloudStack
>          Issue Type: New Feature
>      Security Level: Public(Anyone can view this level - this is the 
> default.) 
>          Components: Management Server
>            Reporter: Paul Angus
>            Assignee: Rohit Yadav
>
> Static command.properties moved to database and made user definable



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to