CLOUDSTACK-5920: IAM service plugin.

This commit is contained in:
Min Chen 2014-03-04 17:52:19 -08:00
parent adb29b2140
commit c28450c1cd
27 changed files with 4321 additions and 0 deletions

View File

@ -0,0 +1,58 @@
<!--
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.
-->
<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>
<artifactId>cloud-plugin-iam</artifactId>
<name>Apache CloudStack IAM - Plugin</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-service-iam</artifactId>
<version>4.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-schema</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-iam</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
# 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.
name=iam-access-checkers
parent=api

View File

@ -0,0 +1,35 @@
<!--
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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
<bean id="RoleBasedAPIAccessChecker" class="org.apache.cloudstack.iam.RoleBasedAPIAccessChecker" />
<bean id="RoleBasedEntityAccessChecker" class="org.apache.cloudstack.iam.RoleBasedEntityAccessChecker" />
<bean id="RoleBasedEntityQuerySelector" class="org.apache.cloudstack.iam.RoleBasedEntityQuerySelector" />
<bean id="IAMApiServiceImpl" class="org.apache.cloudstack.iam.IAMApiServiceImpl" />
</beans>

View File

@ -0,0 +1,127 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "addAccountToIAMGroup", description = "add account to an iam group", responseObject = IAMGroupResponse.class)
public class AddAccountToIAMGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(AddAccountToIAMGroupCmd.class.getName());
private static final String s_name = "addaccounttoiamgroupresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMGroupResponse.class,
required = true, description = "The ID of the iam group")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the iam group.")
private List<Long> accountIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getAccountIdList() {
return accountIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM group Id: " + getId());
IAMGroup result = _iamApiSrv.addAccountsToGroup(accountIdList, id);
if (result != null){
IAMGroupResponse response = _iamApiSrv.createIAMGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add accounts to iam group");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_UPDATE;
}
@Override
public String getEventDescription() {
return "adding accounts to iam group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,155 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.db.EntityManager;
@APICommand(name = "addIAMPermissionToIAMPolicy", description = "Add IAM permission to an iam policy", responseObject = IAMPolicyResponse.class)
public class AddIAMPermissionToIAMPolicyCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(AddIAMPermissionToIAMPolicyCmd.class.getName());
private static final String s_name = "addiampermissiontoiampolicyresponse";
@Inject
public IAMApiService _iamApiSrv;
@Inject
public EntityManager _entityMgr;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMPolicyResponse.class,
required = true, description = "The ID of the iam policy")
private Long id;
@Parameter(name = ApiConstants.IAM_ACTION, type = CommandType.STRING, required = true, description = "action api name.")
private String action;
@Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, required = false, description = "entity class simple name.")
private String entityType;
@Parameter(name = ApiConstants.IAM_SCOPE, type = CommandType.STRING,
required = false, description = "iam permission scope")
private String scope;
@Parameter(name = ApiConstants.IAM_SCOPE_ID, type = CommandType.STRING, required = false, description = "The UUID of the permission scope id")
private String scopeId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public String getAction() {
return action;
}
public String getEntityType() {
return entityType;
}
public String getScope() {
return scope;
}
public Long getScopeId() {
// here we will convert the passed String UUID to Long ID since internally we store it as entity internal ID.
return _iamApiSrv.getPermissionScopeId(scope, entityType, scopeId);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM policy Id: " + getId());
// Only explicit ALLOW is supported for this release, no explicit deny
IAMPolicy result = _iamApiSrv.addIAMPermissionToIAMPolicy(id, entityType, PermissionScope.valueOf(scope),
getScopeId(), action, Permission.Allow, false);
if (result != null) {
IAMPolicyResponse response = _iamApiSrv.createIAMPolicyResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to grant permission to iam policy "
+ getId());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_POLICY_GRANT;
}
@Override
public String getEventDescription() {
return "granting permission to iam policy";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMPolicy;
}
}

View File

@ -0,0 +1,122 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "attachIAMPolicyToAccount", description = "attach iam policy to accounts", responseObject = SuccessResponse.class)
public class AttachIAMPolicyToAccountCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(AttachIAMPolicyToAccountCmd.class.getName());
private static final String s_name = "attachiampolicytoaccountresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMPolicyResponse.class,
required = true, description = "The ID of the iam policy")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that the policy will attach to.")
private List<Long> accountIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getAccountIdList() {
return accountIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM policy Id: " + getId());
_iamApiSrv.attachIAMPolicyToAccounts(id, accountIdList);
SuccessResponse response = new SuccessResponse();
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_ACCOUNT_POLICY_UPDATE;
}
@Override
public String getEventDescription() {
return "adding IAM policy to accounts";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.Account;
}
}

View File

@ -0,0 +1,127 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "attachIAMPolicyToIAMGroup", description = "attach iam policy to an iam group", responseObject = IAMGroupResponse.class)
public class AttachIAMPolicyToIAMGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(AttachIAMPolicyToIAMGroupCmd.class.getName());
private static final String s_name = "attachiampolicytoiamgroupresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMGroupResponse.class,
required = true, description = "The ID of the iam group")
private Long id;
@ACL
@Parameter(name = ApiConstants.IAM_POLICIES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = IAMPolicyResponse.class, description = "comma separated list of iam policy id that are going to be applied to the iam group.")
private List<Long> policyIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getPolicyIdList() {
return policyIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM group Id: " + getId());
IAMGroup result = _iamApiSrv.attachIAMPoliciesToGroup(policyIdList, id);
if (result != null){
IAMGroupResponse response = _iamApiSrv.createIAMGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to iam group");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_UPDATE;
}
@Override
public String getEventDescription() {
return "adding iam roles to iam group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,168 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.user.Account;
@APICommand(name = "createIAMGroup", responseObject = IAMGroupResponse.class, description = "Creates an IAM group")
public class CreateIAMGroupCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateIAMGroupCmd.class.getName());
private static final String s_name = "createiamgroupresponse";
@Inject
public IAMApiService _iamApiSrv;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the iam group. Must be used with domainId.")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the iam group", entityType = DomainResponse.class)
private Long domainId;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the iam group")
private String description;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the iam group")
private String name;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public String getDescription() {
return description;
}
public Long getDomainId() {
return domainId;
}
public String getName() {
return name;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Account account = CallContext.current().getCallingAccount();
if ((account == null) || _accountService.isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
// command to SYSTEM so ERROR events
// are tracked
}
@Override
public void execute() {
IAMGroup grp = _entityMgr.findById(IAMGroup.class, getEntityId());
if (grp != null) {
IAMGroupResponse response = _iamApiSrv.createIAMGroupResponse(grp);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create iam group:" + name);
}
}
@Override
public void create() throws ResourceAllocationException {
Account account = CallContext.current().getCallingAccount();
IAMGroup result = _iamApiSrv.createIAMGroup(account, name, description);
if (result != null) {
setEntityId(result.getId());
setEntityUuid(result.getUuid());
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create iam group entity" + name);
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_CREATE;
}
@Override
public String getEventDescription() {
return "creating IAM group";
}
@Override
public String getCreateEventType() {
return EventTypes.EVENT_IAM_GROUP_CREATE;
}
@Override
public String getCreateEventDescription() {
return "creating IAM group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,175 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMPolicy;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.user.Account;
@APICommand(name = "createIAMPolicy", responseObject = IAMPolicyResponse.class, description = "Creates an iam policy")
public class CreateIAMPolicyCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateIAMPolicyCmd.class.getName());
private static final String s_name = "createiampolicyresponse";
@Inject
public IAMApiService _iamApiSrv;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the iam policy. Must be used with domainId.")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the iam policy", entityType = DomainResponse.class)
private Long domainId;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the iam policy")
private String description;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the iam policy")
private String name;
@ACL
@Parameter(name = ApiConstants.IAM_PARENT_POLICY_ID, type = CommandType.UUID, description = "The ID of parent iam policy.", entityType = IAMPolicyResponse.class)
private Long parentPolicyId;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public String getDescription() {
return description;
}
public Long getDomainId() {
return domainId;
}
public String getName() {
return name;
}
public Long getParentPolicyId() {
return parentPolicyId;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Account account = CallContext.current().getCallingAccount();
if ((account == null) || _accountService.isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
// command to SYSTEM so ERROR events
// are tracked
}
@Override
public void execute() {
IAMPolicy policy = _entityMgr.findById(IAMPolicy.class, getEntityId());
if (policy != null) {
IAMPolicyResponse response = _iamApiSrv.createIAMPolicyResponse(policy);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create iam policy:" + name);
}
}
@Override
public void create() throws ResourceAllocationException {
Account account = CallContext.current().getCallingAccount();
IAMPolicy result = _iamApiSrv.createIAMPolicy(account, name, description, parentPolicyId);
if (result != null) {
setEntityId(result.getId());
setEntityUuid(result.getUuid());
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create iam policy entity" + name);
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_POLICY_CREATE;
}
@Override
public String getEventDescription() {
return "creating IAM policy";
}
@Override
public String getCreateEventType() {
return EventTypes.EVENT_IAM_POLICY_CREATE;
}
@Override
public String getCreateEventDescription() {
return "creating IAM policy";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMPolicy;
}
}

View File

@ -0,0 +1,102 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.iam.IAMApiService;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
@APICommand(name = "deleteIAMGroup", description = "Deletes acl group", responseObject = SuccessResponse.class)
public class DeleteIAMGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteIAMGroupCmd.class.getName());
private static final String s_name = "deleteaclgroupresponse";
@Inject
public IAMApiService _aclApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the acl group.", required = true, entityType = IAMGroupResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute(){
boolean result = _aclApiSrv.deleteIAMGroup(id);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete acl group");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_DELETE;
}
@Override
public String getEventDescription() {
return "Deleting Acl group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,102 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
@APICommand(name = "deleteIAMPolicy", description = "Deletes iam policy", responseObject = SuccessResponse.class)
public class DeleteIAMPolicyCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteIAMPolicyCmd.class.getName());
private static final String s_name = "deleteiampolicyresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the iam policy.", required = true, entityType = IAMPolicyResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute(){
boolean result = _iamApiSrv.deleteIAMPolicy(id);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete iam policy");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_POLICY_DELETE;
}
@Override
public String getEventDescription() {
return "Deleting IAM policy";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMPolicy;
}
}

View File

@ -0,0 +1,88 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
@APICommand(name = "listIAMGroups", description = "Lists iam groups", responseObject = IAMGroupResponse.class)
public class ListIAMGroupsCmd extends BaseListDomainResourcesCmd {
public static final Logger s_logger = Logger.getLogger(ListIAMGroupsCmd.class.getName());
private static final String s_name = "listiamgroupsresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists iam groups by name")
private String iamGroupName;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the iam group by the id provided", entityType = IAMGroupResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getIAMGroupName() {
return iamGroupName;
}
public Long getId(){
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
ListResponse<IAMGroupResponse> response = _iamApiSrv.listIAMGroups(id, iamGroupName, getDomainId(),
getStartIndex(), getPageSizeVal());
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,88 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
@APICommand(name = "listIAMPolicies", description = "Lists IAM policies", responseObject = IAMPolicyResponse.class)
public class ListIAMPoliciesCmd extends BaseListDomainResourcesCmd {
public static final Logger s_logger = Logger.getLogger(ListIAMPoliciesCmd.class.getName());
private static final String s_name = "listiampoliciesresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists iam policies by name")
private String iamPolicyName;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the iam policy by the id provided", entityType = IAMPolicyResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getIAMPolicyName() {
return iamPolicyName;
}
public Long getId(){
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
ListResponse<IAMPolicyResponse> response = _iamApiSrv.listIAMPolicies(id, iamPolicyName, getDomainId(),
getStartIndex(), getPageSizeVal());
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMPolicy;
}
}

View File

@ -0,0 +1,127 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "removeAccountFromIAMGroup", description = "remove accounts from an iam group", responseObject = IAMGroupResponse.class)
public class RemoveAccountFromIAMGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(RemoveAccountFromIAMGroupCmd.class.getName());
private static final String s_name = "removeaccountfromiamgroupresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMGroupResponse.class,
required = true, description = "The ID of the iam group")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the iam group.")
private List<Long> accountIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getAccountIdList() {
return accountIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM group Id: " + getId());
IAMGroup result = _iamApiSrv.removeAccountsFromGroup(accountIdList, id);
if (result != null){
IAMGroupResponse response = _iamApiSrv.createIAMGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove accounts from iam group");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_UPDATE;
}
@Override
public String getEventDescription() {
return "removing accounts from iam group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,148 @@
// 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.api.command.iam;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.iam.api.IAMPolicy;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "removeIAMPermissionFromIAMPolicy", description = "Remove iam permission from an iam policy", responseObject = IAMPolicyResponse.class)
public class RemoveIAMPermissionFromIAMPolicyCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(RemoveIAMPermissionFromIAMPolicyCmd.class.getName());
private static final String s_name = "removeiampermissionfromiampolicyresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMPolicyResponse.class,
required = true, description = "The ID of the iam policy")
private Long id;
@Parameter(name = ApiConstants.IAM_ACTION, type = CommandType.STRING, required = true, description = "action api name.")
private String action;
@Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, required = false, description = "entity class simple name.")
private String entityType;
@Parameter(name = ApiConstants.IAM_SCOPE, type = CommandType.STRING,
required = false, description = "iam permission scope")
private String scope;
@Parameter(name = ApiConstants.IAM_SCOPE_ID, type = CommandType.STRING, required = false, description = "The ID of the permission scope id")
private String scopeId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public String getAction() {
return action;
}
public String getEntityType() {
return entityType;
}
public String getScope() {
return scope;
}
public Long getScopeId() {
// here we will convert the passed String UUID to Long ID since internally we store it as entity internal ID.
return _iamApiSrv.getPermissionScopeId(scope, entityType, scopeId);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM policy Id: " + getId());
IAMPolicy result = _iamApiSrv.removeIAMPermissionFromIAMPolicy(id, entityType, PermissionScope.valueOf(scope), getScopeId(), action);
if (result != null) {
IAMPolicyResponse response = _iamApiSrv.createIAMPolicyResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove permission from iam policy " + getId());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_POLICY_REVOKE;
}
@Override
public String getEventDescription() {
return "removing permission from iam policy";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMPolicy;
}
}

View File

@ -0,0 +1,122 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.IAMApiService;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "removeIAMPolicyFromAccount", description = "remove iam policy from accounts", responseObject = SuccessResponse.class)
public class RemoveIAMPolicyFromAccountCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(RemoveIAMPolicyFromAccountCmd.class.getName());
private static final String s_name = "removeiampolicyfromaccountresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMPolicyResponse.class,
required = true, description = "The ID of the iam group")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of iam policy id that are going to be applied to the iam group.")
private List<Long> accountIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getAccountIdList() {
return accountIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM policy Id: " + getId());
_iamApiSrv.removeIAMPolicyFromAccounts(id, accountIdList);
SuccessResponse response = new SuccessResponse();
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_ACCOUNT_POLICY_UPDATE;
}
@Override
public String getEventDescription() {
return "removing iam policy from accounts";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.Account;
}
}

View File

@ -0,0 +1,127 @@
// 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.api.command.iam;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "removeIAMPolicyFromIAMGroup", description = "remove iam policy from an iam group", responseObject = IAMGroupResponse.class)
public class RemoveIAMPolicyFromIAMGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(RemoveIAMPolicyFromIAMGroupCmd.class.getName());
private static final String s_name = "removeiampolicyfromiamgroupresponse";
@Inject
public IAMApiService _iamApiSrv;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IAMGroupResponse.class,
required = true, description = "The ID of the iam group")
private Long id;
@ACL
@Parameter(name = ApiConstants.IAM_POLICIES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = IAMPolicyResponse.class, description = "comma separated list of iam policy id that are going to be applied to the iam group.")
private List<Long> policyIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getRoleIdList() {
return policyIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("IAM group Id: " + getId());
IAMGroup result = _iamApiSrv.removeIAMPoliciesFromGroup(policyIdList, id);
if (result != null){
IAMGroupResponse response = _iamApiSrv.createIAMGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to iam group");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_IAM_GROUP_UPDATE;
}
@Override
public String getEventDescription() {
return "removing IAM roles from IAM group";
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.IAMGroup;
}
}

View File

@ -0,0 +1,193 @@
// 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.api.response.iam;
import java.util.LinkedHashSet;
import java.util.Set;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
import org.apache.cloudstack.iam.api.IAMGroup;
import com.cloud.serializer.Param;
@SuppressWarnings("unused")
@EntityReference(value = IAMGroup.class)
public class IAMGroupResponse extends BaseResponse implements ControlledViewEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the iam group")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the iam group")
private String name;
@SerializedName(ApiConstants.DESCRIPTION)
@Param(description = "the description of the iam group")
private String description;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID of the iam group")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the domain name of the iam role")
private String domainName;
@SerializedName(ApiConstants.ACCOUNT)
@Param(description = "the account owning the policy")
private String accountName;
@SerializedName(ApiConstants.IAM_MEMBER_ACCOUNTS)
@Param(description = "account names assigned to this iam group ")
private Set<String> accountNameList;
@SerializedName(ApiConstants.IAM_POLICIES)
@Param(description = "iam policies attached to this iam group ")
private Set<String> policyNameList;
public IAMGroupResponse() {
accountNameList = new LinkedHashSet<String>();
policyNameList = new LinkedHashSet<String>();
}
@Override
public String getObjectId() {
return getId();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public void setDomainId(String domainId) {
this.domainId = domainId;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public void setProjectId(String projectId) {
// TODO Auto-generated method stub
}
@Override
public void setProjectName(String projectName) {
// TODO Auto-generated method stub
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getDomainId() {
return domainId;
}
public String getDomainName() {
return domainName;
}
public String getAccountName() {
return accountName;
}
public Set<String> getAccountNameList() {
return accountNameList;
}
public void setMemberAccounts(Set<String> accts) {
accountNameList = accts;
}
public void addMemberAccount(String acct) {
accountNameList.add(acct);
}
public void setPolicyList(Set<String> policies) {
policyNameList = policies;
}
public void addPolicy(String policy) {
policyNameList.add(policy);
}
public Set<String> getPolicyList() {
return policyNameList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IAMGroupResponse other = (IAMGroupResponse)obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}

View File

@ -0,0 +1,125 @@
// 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.api.response.iam;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.IAMEntityType;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import com.cloud.serializer.Param;
public class IAMPermissionResponse extends BaseResponse {
@SerializedName(ApiConstants.IAM_ACTION)
@Param(description = "action of this permission")
private String action;
@SerializedName(ApiConstants.ENTITY_TYPE)
@Param(description = "the entity type of this permission")
private IAMEntityType entityType;
@SerializedName(ApiConstants.IAM_SCOPE)
@Param(description = "scope of this permission")
private PermissionScope scope;
@SerializedName(ApiConstants.IAM_SCOPE_ID)
@Param(description = "scope id of this permission")
private Long scopeId;
@SerializedName(ApiConstants.IAM_ALLOW_DENY)
@Param(description = "allow or deny of this permission")
private IAMPolicyPermission.Permission permission;
public IAMEntityType getEntityType() {
return entityType;
}
public void setEntityType(IAMEntityType entityType) {
this.entityType = entityType;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public PermissionScope getScope() {
return scope;
}
public void setScope(PermissionScope scope) {
this.scope = scope;
}
public Long getScopeId() {
return scopeId;
}
public void setScopeId(Long scopeId) {
this.scopeId = scopeId;
}
public IAMPolicyPermission.Permission getPermission() {
return permission;
}
public void setPermission(IAMPolicyPermission.Permission permission) {
this.permission = permission;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((action == null) ? 0 : action.hashCode());
result = prime * result + ((entityType == null) ? 0 : entityType.hashCode());
result = prime * result + ((scope == null) ? 0 : scope.hashCode());
result = prime * result + ((scopeId == null) ? 0 : scopeId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IAMPermissionResponse other = (IAMPermissionResponse) obj;
if ((entityType == null && other.entityType != null) || !entityType.equals(other.entityType)) {
return false;
} else if ((action == null && other.action != null) || !action.equals(other.action)) {
return false;
} else if ((scope == null && other.scope != null) || !scope.equals(other.scope)) {
return false;
} else if ((scopeId == null && other.scopeId != null) || !scopeId.equals(other.scopeId)) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,177 @@
// 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.api.response.iam;
import java.util.LinkedHashSet;
import java.util.Set;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
import org.apache.cloudstack.iam.api.IAMPolicy;
import com.cloud.serializer.Param;
@SuppressWarnings("unused")
@EntityReference(value = IAMPolicy.class)
public class IAMPolicyResponse extends BaseResponse implements ControlledViewEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the iam policy")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the iam policy")
private String name;
@SerializedName(ApiConstants.DESCRIPTION)
@Param(description = "the description of the iam policy")
private String description;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID of the iam policy")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the domain name of the iam policy")
private String domainName;
@SerializedName(ApiConstants.ACCOUNT)
@Param(description = "the account owning the policy")
private String accountName;
@SerializedName(ApiConstants.IAM_PERMISSIONS)
@Param(description = "set of permissions for the iam policy")
private Set<IAMPermissionResponse> permissionList;
public IAMPolicyResponse() {
permissionList = new LinkedHashSet<IAMPermissionResponse>();
}
@Override
public String getObjectId() {
return getId();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public void setDomainId(String domainId) {
this.domainId = domainId;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public Set<IAMPermissionResponse> getPermissionList() {
return permissionList;
}
public void setPermissionList(Set<IAMPermissionResponse> perms) {
permissionList = perms;
}
public void addPermission(IAMPermissionResponse perm) {
permissionList.add(perm);
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public void setProjectId(String projectId) {
// TODO Auto-generated method stub
}
@Override
public void setProjectName(String projectName) {
// TODO Auto-generated method stub
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getDomainId() {
return domainId;
}
public String getDomainName() {
return domainName;
}
public String getAccountName() {
return accountName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IAMPolicyResponse other = (IAMPolicyResponse) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}

View File

@ -0,0 +1,87 @@
// 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.iam;
import java.util.List;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import com.cloud.user.Account;
import com.cloud.utils.component.PluggableService;
public interface IAMApiService extends PluggableService {
/* ACL group related interfaces */
IAMGroup createIAMGroup(Account caller, String iamGroupName, String description);
boolean deleteIAMGroup(Long iamGroupId);
List<IAMGroup> listIAMGroups(long accountId);
IAMGroup addAccountsToGroup(List<Long> acctIds, Long groupId);
IAMGroup removeAccountsFromGroup(List<Long> acctIds, Long groupId);
/* IAM Policy related interfaces */
IAMPolicy createIAMPolicy(Account caller, String iamPolicyName, String description, Long parentPolicyId);
boolean deleteIAMPolicy(long iamPolicyId);
List<IAMPolicy> listIAMPolicies(long accountId);
IAMGroup attachIAMPoliciesToGroup(List<Long> policyIds, Long groupId);
IAMGroup removeIAMPoliciesFromGroup(List<Long> policyIds, Long groupId);
void attachIAMPolicyToAccounts(Long policyId, List<Long> accountIds);
void removeIAMPolicyFromAccounts(Long policyId, List<Long> accountIds);
IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId,
String action, Permission perm, Boolean recursive);
IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, String action);
IAMPolicyPermission getIAMPolicyPermission(long accountId, String entityType, String action);
/* Utility routine to grant/revoke invidivual resource to list of accounts */
void grantEntityPermissioinToAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds);
void revokeEntityPermissioinFromAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds);
/* Response Generation */
IAMPolicyResponse createIAMPolicyResponse(IAMPolicy policy);
IAMGroupResponse createIAMGroupResponse(IAMGroup group);
ListResponse<IAMGroupResponse> listIAMGroups(Long iamGroupId, String iamGroupName,
Long domainId, Long startIndex, Long pageSize);
ListResponse<IAMPolicyResponse> listIAMPolicies(Long iamPolicyId, String iamPolicyName,
Long domainId, Long startIndex, Long pageSize);
// Convert passed scope uuid to internal scope long id
Long getPermissionScopeId(String scope, String entityType, String scopeId);
}

View File

@ -0,0 +1,800 @@
// 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.iam;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.IAMEntityType;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.InternalIdentity;
import org.apache.cloudstack.api.command.iam.AddAccountToIAMGroupCmd;
import org.apache.cloudstack.api.command.iam.AddIAMPermissionToIAMPolicyCmd;
import org.apache.cloudstack.api.command.iam.AttachIAMPolicyToAccountCmd;
import org.apache.cloudstack.api.command.iam.AttachIAMPolicyToIAMGroupCmd;
import org.apache.cloudstack.api.command.iam.CreateIAMGroupCmd;
import org.apache.cloudstack.api.command.iam.CreateIAMPolicyCmd;
import org.apache.cloudstack.api.command.iam.DeleteIAMGroupCmd;
import org.apache.cloudstack.api.command.iam.DeleteIAMPolicyCmd;
import org.apache.cloudstack.api.command.iam.ListIAMGroupsCmd;
import org.apache.cloudstack.api.command.iam.ListIAMPoliciesCmd;
import org.apache.cloudstack.api.command.iam.RemoveAccountFromIAMGroupCmd;
import org.apache.cloudstack.api.command.iam.RemoveIAMPermissionFromIAMPolicyCmd;
import org.apache.cloudstack.api.command.iam.RemoveIAMPolicyFromAccountCmd;
import org.apache.cloudstack.api.command.iam.RemoveIAMPolicyFromIAMGroupCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.api.response.iam.IAMPermissionResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import org.apache.cloudstack.iam.api.IAMService;
import org.apache.cloudstack.iam.server.IAMGroupVO;
import org.apache.cloudstack.iam.server.IAMPolicyVO;
import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleVO;
import com.cloud.api.ApiServerService;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.event.EventVO;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.UserIpv6AddressVO;
import com.cloud.network.VpnUserVO;
import com.cloud.network.as.AutoScalePolicyVO;
import com.cloud.network.as.AutoScaleVmGroupVO;
import com.cloud.network.as.AutoScaleVmProfileVO;
import com.cloud.network.as.ConditionVO;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.MonitoringServiceVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.Site2SiteCustomerGatewayVO;
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
import com.cloud.network.dao.Site2SiteVpnGatewayVO;
import com.cloud.network.dao.SslCertVO;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.vpc.StaticRouteVO;
import com.cloud.network.vpc.VpcGatewayVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.projects.ProjectInvitationVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.tags.ResourceTagVO;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.DomainManager;
import com.cloud.user.SSHKeyPairVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.NicIpAliasVO;
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.snapshot.VMSnapshotVO;
@Local(value = {IAMApiService.class})
public class IAMApiServiceImpl extends ManagerBase implements IAMApiService, Manager {
public static final Logger s_logger = Logger.getLogger(IAMApiServiceImpl.class);
private String _name;
@Inject
ApiServerService _apiServer;
@Inject
IAMService _iamSrv;
@Inject
DomainDao _domainDao;
@Inject
AccountDao _accountDao;
@Inject
AccountManager _accountMgr;
@Inject
MessageBus _messageBus;
@Inject
EntityManager _entityMgr;
private static final Map<IAMEntityType, Class<?>> s_typeMap = new HashMap<IAMEntityType, Class<?>>();
static {
s_typeMap.put(IAMEntityType.VirtualMachine, VMInstanceVO.class);
s_typeMap.put(IAMEntityType.Volume, VolumeVO.class);
s_typeMap.put(IAMEntityType.ResourceTag, ResourceTagVO.class);
s_typeMap.put(IAMEntityType.Account, AccountVO.class);
s_typeMap.put(IAMEntityType.AffinityGroup, AffinityGroupVO.class);
s_typeMap.put(IAMEntityType.AutoScalePolicy, AutoScalePolicyVO.class);
s_typeMap.put(IAMEntityType.AutoScaleVmProfile, AutoScaleVmProfileVO.class);
s_typeMap.put(IAMEntityType.AutoScaleVmGroup, AutoScaleVmGroupVO.class);
s_typeMap.put(IAMEntityType.Condition, ConditionVO.class);
s_typeMap.put(IAMEntityType.Vpc, VpcVO.class);
s_typeMap.put(IAMEntityType.VpcGateway, VpcGatewayVO.class);
s_typeMap.put(IAMEntityType.PrivateGateway, RemoteAccessVpnVO.class);
s_typeMap.put(IAMEntityType.VpnUser, VpnUserVO.class);
s_typeMap.put(IAMEntityType.VMSnapshot, VMSnapshotVO.class);
s_typeMap.put(IAMEntityType.VirtualMachineTemplate, VMTemplateVO.class);
s_typeMap.put(IAMEntityType.UserIpv6Address, UserIpv6AddressVO.class);
s_typeMap.put(IAMEntityType.StaticRoute, StaticRouteVO.class);
s_typeMap.put(IAMEntityType.SSHKeyPair, SSHKeyPairVO.class);
s_typeMap.put(IAMEntityType.Snapshot, SnapshotVO.class);
s_typeMap.put(IAMEntityType.Site2SiteVpnGateway, Site2SiteVpnGatewayVO.class);
s_typeMap.put(IAMEntityType.Site2SiteCustomerGateway, Site2SiteCustomerGatewayVO.class);
s_typeMap.put(IAMEntityType.Site2SiteVpnConnection, Site2SiteVpnConnectionVO.class);
s_typeMap.put(IAMEntityType.SecurityGroup, SecurityGroupVO.class);
s_typeMap.put(IAMEntityType.RemoteAccessVpn, RemoteAccessVpnVO.class);
s_typeMap.put(IAMEntityType.PublicIpAddress, IPAddressVO.class);
s_typeMap.put(IAMEntityType.ProjectInvitation, ProjectInvitationVO.class);
s_typeMap.put(IAMEntityType.NicSecondaryIp, NicSecondaryIpVO.class);
s_typeMap.put(IAMEntityType.NicIpAlias, NicIpAliasVO.class);
s_typeMap.put(IAMEntityType.Network, NetworkVO.class);
s_typeMap.put(IAMEntityType.IpAddress, IPAddressVO.class);
s_typeMap.put(IAMEntityType.InstanceGroup, InstanceGroupVO.class);
s_typeMap.put(IAMEntityType.GlobalLoadBalancerRule, GlobalLoadBalancerRuleVO.class);
s_typeMap.put(IAMEntityType.FirewallRule, FirewallRuleVO.class);
s_typeMap.put(IAMEntityType.PortForwardingRule, PortForwardingRuleVO.class);
s_typeMap.put(IAMEntityType.Event, EventVO.class);
s_typeMap.put(IAMEntityType.AsyncJob, AsyncJobVO.class);
s_typeMap.put(IAMEntityType.IAMGroup, IAMGroupVO.class);
s_typeMap.put(IAMEntityType.IAMPolicy, IAMPolicyVO.class);
s_typeMap.put(IAMEntityType.MonitorService, MonitoringServiceVO.class);
s_typeMap.put(IAMEntityType.SSLCert, SslCertVO.class);
}
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_messageBus.subscribe(AccountManager.MESSAGE_ADD_ACCOUNT_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
HashMap<Long, Long> acctGroupMap = (HashMap<Long, Long>) obj;
for (Long accountId : acctGroupMap.keySet()) {
Long groupId = acctGroupMap.get(accountId);
s_logger.debug("MessageBus message: new Account Added: " + accountId + ", adding it to groupId :"
+ groupId);
addAccountToIAMGroup(accountId, groupId);
// add it to domain group too
AccountVO account = _accountDao.findById(accountId);
Domain domain = _domainDao.findById(account.getDomainId());
if (domain != null) {
List<IAMGroup> domainGroups = listDomainGroup(domain);
if (domainGroups != null) {
for (IAMGroup group : domainGroups) {
addAccountToIAMGroup(accountId, new Long(group.getId()));
}
}
}
}
}
});
_messageBus.subscribe(AccountManager.MESSAGE_REMOVE_ACCOUNT_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long accountId = ((Long) obj);
if (accountId != null) {
s_logger.debug("MessageBus message: Account removed: " + accountId
+ ", releasing the group associations");
removeAccountFromIAMGroups(accountId);
}
}
});
_messageBus.subscribe(DomainManager.MESSAGE_ADD_DOMAIN_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long domainId = ((Long) obj);
if (domainId != null) {
s_logger.debug("MessageBus message: new Domain created: " + domainId + ", creating a new group");
Domain domain = _domainDao.findById(domainId);
_iamSrv.createIAMGroup("DomainGrp-" + domain.getUuid(), "Domain group", domain.getPath());
}
}
});
_messageBus.subscribe(DomainManager.MESSAGE_REMOVE_DOMAIN_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long domainId = ((Long) obj);
if (domainId != null) {
s_logger.debug("MessageBus message: Domain removed: " + domainId + ", removing the domain group");
Domain domain = _domainDao.findById(domainId);
List<IAMGroup> groups = listDomainGroup(domain);
for (IAMGroup group : groups) {
_iamSrv.deleteIAMGroup(group.getId());
}
}
}
});
_messageBus.subscribe(TemplateManager.MESSAGE_REGISTER_PUBLIC_TEMPLATE_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long templateId = (Long)obj;
if (templateId != null) {
s_logger.debug("MessageBus message: new public template registered: " + templateId + ", grant permission to domain admin and normal user policies");
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
}
}
});
_messageBus.subscribe(TemplateManager.MESSAGE_RESET_TEMPLATE_PERMISSION_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long templateId = (Long)obj;
if (templateId != null) {
s_logger.debug("MessageBus message: reset template permission: " + templateId);
resetTemplatePermission(templateId);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Pair<IAMEntityType, Long> entity = (Pair<IAMEntityType, Long>)obj;
if (entity != null) {
String entityType = entity.first().toString();
Long entityId = entity.second();
s_logger.debug("MessageBus message: delete an entity: (" + entityType + "," + entityId + "), remove its related permission");
_iamSrv.removeIAMPermissionForEntity(entityType, entityId);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_GRANT_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Map<String, Object> permit = (Map<String, Object>)obj;
if (permit != null) {
String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE);
Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID);
AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE);
String action = (String)permit.get(ApiConstants.IAM_ACTION);
List<Long> acctIds = (List<Long>)permit.get(ApiConstants.ACCOUNTS);
s_logger.debug("MessageBus message: grant accounts permission to an entity: (" + entityType + "," + entityId + ")");
grantEntityPermissioinToAccounts(entityType, entityId, accessType, action, acctIds);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_REVOKE_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Map<String, Object> permit = (Map<String, Object>)obj;
if (permit != null) {
String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE);
Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID);
AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE);
String action = (String)permit.get(ApiConstants.IAM_ACTION);
List<Long> acctIds = (List<Long>)permit.get(ApiConstants.ACCOUNTS);
s_logger.debug("MessageBus message: revoke from accounts permission to an entity: (" + entityType + "," + entityId + ")");
revokeEntityPermissioinFromAccounts(entityType, entityId, accessType, action, acctIds);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Map<String, Object> params = (Map<String, Object>) obj;
if (params != null) {
addDomainWideResourceAccess(params);
}
}
});
return super.configure(name, params);
}
private void addDomainWideResourceAccess(Map<String, Object> params) {
IAMEntityType entityType = (IAMEntityType)params.get(ApiConstants.ENTITY_TYPE);
Long entityId = (Long) params.get(ApiConstants.ENTITY_ID);
Long domainId = (Long) params.get(ApiConstants.DOMAIN_ID);
Boolean isRecursive = (Boolean) params.get(ApiConstants.SUBDOMAIN_ACCESS);
if (entityType == IAMEntityType.Network) {
createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType.toString(),
entityId, "listNetworks", AccessType.UseEntry, domainId, isRecursive);
} else if (entityType == IAMEntityType.AffinityGroup) {
createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide affinityGroup", entityType.toString(),
entityId, "listAffinityGroups", AccessType.UseEntry, domainId, isRecursive);
}
}
private void createPolicyAndAddToDomainGroup(String policyName, String description, String entityType,
Long entityId, String action, AccessType accessType, Long domainId, Boolean recursive) {
Domain domain = _domainDao.findById(domainId);
if (domain != null) {
IAMPolicy policy = _iamSrv.createIAMPolicy(policyName, description, null, domain.getPath());
_iamSrv.addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE.toString(),
entityId, action, accessType.toString(), Permission.Allow, recursive);
List<Long> policyList = new ArrayList<Long>();
policyList.add(new Long(policy.getId()));
List<IAMGroup> domainGroups = listDomainGroup(domain);
if (domainGroups != null) {
for (IAMGroup group : domainGroups) {
_iamSrv.attachIAMPoliciesToGroup(policyList, group.getId());
}
}
}
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_CREATE, eventDescription = "Creating Acl Group", create = true)
public IAMGroup createIAMGroup(Account caller, String iamGroupName, String description) {
Long domainId = caller.getDomainId();
Domain callerDomain = _domainDao.findById(domainId);
if (callerDomain == null) {
throw new InvalidParameterValueException("Caller does not have a domain");
}
return _iamSrv.createIAMGroup(iamGroupName, description, callerDomain.getPath());
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_DELETE, eventDescription = "Deleting Acl Group")
public boolean deleteIAMGroup(final Long iamGroupId) {
return _iamSrv.deleteIAMGroup(iamGroupId);
}
@Override
public List<IAMGroup> listIAMGroups(long accountId) {
return _iamSrv.listIAMGroups(accountId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_UPDATE, eventDescription = "Adding accounts to acl group")
public IAMGroup addAccountsToGroup(final List<Long> acctIds, final Long groupId) {
return _iamSrv.addAccountsToGroup(acctIds, groupId);
}
private void removeAccountFromIAMGroups(long accountId) {
List<IAMGroup> groups = listIAMGroups(accountId);
List<Long> accts = new ArrayList<Long>();
accts.add(accountId);
if (groups != null) {
for (IAMGroup grp : groups) {
removeAccountsFromGroup(accts, grp.getId());
}
}
}
private void addAccountToIAMGroup(long accountId, long groupId) {
List<Long> accts = new ArrayList<Long>();
accts.add(accountId);
addAccountsToGroup(accts, groupId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_UPDATE, eventDescription = "Removing accounts from acl group")
public IAMGroup removeAccountsFromGroup(final List<Long> acctIds, final Long groupId) {
return _iamSrv.removeAccountsFromGroup(acctIds, groupId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_CREATE, eventDescription = "Creating IAM Policy", create = true)
public IAMPolicy createIAMPolicy(Account caller, final String iamPolicyName, final String description, final Long parentPolicyId) {
Long domainId = caller.getDomainId();
Domain callerDomain = _domainDao.findById(domainId);
if (callerDomain == null) {
throw new InvalidParameterValueException("Caller does not have a domain");
}
return _iamSrv.createIAMPolicy(iamPolicyName, description, parentPolicyId, callerDomain.getPath());
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_DELETE, eventDescription = "Deleting IAM Policy")
public boolean deleteIAMPolicy(final long iamPolicyId) {
return _iamSrv.deleteIAMPolicy(iamPolicyId);
}
@Override
public List<IAMPolicy> listIAMPolicies(long accountId) {
return _iamSrv.listIAMPolicies(accountId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_UPDATE, eventDescription = "Attaching policy to acl group")
public IAMGroup attachIAMPoliciesToGroup(final List<Long> policyIds, final Long groupId) {
return _iamSrv.attachIAMPoliciesToGroup(policyIds, groupId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_GROUP_UPDATE, eventDescription = "Removing policies from acl group")
public IAMGroup removeIAMPoliciesFromGroup(final List<Long> policyIds, final Long groupId) {
return _iamSrv.removeIAMPoliciesFromGroup(policyIds, groupId);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_ACCOUNT_POLICY_UPDATE, eventDescription = "Attaching policy to accounts")
public void attachIAMPolicyToAccounts(final Long policyId, final List<Long> accountIds) {
_iamSrv.attachIAMPolicyToAccounts(policyId, accountIds);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_ACCOUNT_POLICY_UPDATE, eventDescription = "Removing policy from accounts")
public void removeIAMPolicyFromAccounts(final Long policyId, final List<Long> accountIds) {
_iamSrv.removeIAMPolicyFromAccounts(policyId, accountIds);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_GRANT, eventDescription = "Granting acl permission to IAM Policy")
public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope,
Long scopeId, String action, Permission perm, Boolean recursive) {
Class<?> cmdClass = _apiServer.getCmdClass(action);
AccessType accessType = null;
if (BaseListCmd.class.isAssignableFrom(cmdClass)) {
accessType = AccessType.UseEntry;
}
return _iamSrv.addIAMPermissionToIAMPolicy(iamPolicyId, entityType, scope.toString(), scopeId, action,
accessType.toString(), perm, recursive);
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_REVOKE, eventDescription = "Revoking acl permission from IAM Policy")
public IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, String action) {
return _iamSrv.removeIAMPermissionFromIAMPolicy(iamPolicyId, entityType, scope.toString(), scopeId, action);
}
@Override
public IAMPolicyPermission getIAMPolicyPermission(long accountId, String entityType, String action) {
List<IAMPolicy> policies = _iamSrv.listIAMPolicies(accountId);
IAMPolicyPermission curPerm = null;
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> perms = _iamSrv.listPolicyPermissionByActionAndEntity(policy.getId(), action,
entityType);
if (perms == null || perms.size() == 0)
continue;
IAMPolicyPermission perm = perms.get(0); // just pick one
if (curPerm == null) {
curPerm = perm;
} else if (PermissionScope.valueOf(perm.getScope()).greaterThan(PermissionScope.valueOf(curPerm.getScope()))) {
// pick the more relaxed allowed permission
curPerm = perm;
}
}
return curPerm;
}
@Override
public IAMPolicyResponse createIAMPolicyResponse(IAMPolicy policy) {
IAMPolicyResponse response = new IAMPolicyResponse();
response.setId(policy.getUuid());
response.setName(policy.getName());
response.setDescription(policy.getDescription());
String domainPath = policy.getPath();
if (domainPath != null) {
DomainVO domain = _domainDao.findDomainByPath(domainPath);
if (domain != null) {
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
}
}
long accountId = policy.getAccountId();
AccountVO owner = _accountDao.findById(accountId);
if (owner != null) {
response.setAccountName(owner.getAccountName());
}
// find permissions associated with this policy
List<IAMPolicyPermission> permissions = _iamSrv.listPolicyPermissions(policy.getId());
if (permissions != null && permissions.size() > 0) {
for (IAMPolicyPermission permission : permissions) {
IAMPermissionResponse perm = new IAMPermissionResponse();
perm.setAction(permission.getAction());
if (permission.getEntityType() != null) {
perm.setEntityType(IAMEntityType.valueOf(permission.getEntityType()));
}
if (permission.getScope() != null) {
perm.setScope(PermissionScope.valueOf(permission.getScope()));
}
perm.setScopeId(permission.getScopeId());
perm.setPermission(permission.getPermission());
response.addPermission(perm);
}
}
response.setObjectName("aclpolicy");
return response;
}
@Override
public IAMGroupResponse createIAMGroupResponse(IAMGroup group) {
IAMGroupResponse response = new IAMGroupResponse();
response.setId(group.getUuid());
response.setName(group.getName());
response.setDescription(group.getDescription());
String domainPath = group.getPath();
if (domainPath != null) {
DomainVO domain = _domainDao.findDomainByPath(domainPath);
if (domain != null) {
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
}
}
long accountId = group.getAccountId();
AccountVO owner = _accountDao.findById(accountId);
if (owner != null) {
response.setAccountName(owner.getAccountName());
}
// find all the members in this group
List<Long> members = _iamSrv.listAccountsByGroup(group.getId());
if (members != null && members.size() > 0) {
for (Long member : members) {
AccountVO mem = _accountDao.findById(member);
if (mem != null) {
response.addMemberAccount(mem.getAccountName());
}
}
}
// find all the policies attached to this group
List<IAMPolicy> policies = _iamSrv.listIAMPoliciesByGroup(group.getId());
if (policies != null && policies.size() > 0) {
for (IAMPolicy policy : policies) {
response.addPolicy(policy.getName());
}
}
response.setObjectName("aclgroup");
return response;
}
public List<IAMGroup> listDomainGroup(Domain domain) {
if (domain != null) {
String domainPath = domain.getPath();
// search for groups
Pair<List<IAMGroup>, Integer> result = _iamSrv.listIAMGroups(null, "DomainGrp-" + domain.getUuid(),
domainPath, null, null);
return result.first();
}
return new ArrayList<IAMGroup>();
}
@Override
public ListResponse<IAMGroupResponse> listIAMGroups(Long iamGroupId, String iamGroupName, Long domainId, Long startIndex, Long pageSize) {
// acl check
Account caller = CallContext.current().getCallingAccount();
Domain domain = null;
if (domainId != null) {
domain = _domainDao.findById(domainId);
if (domain == null) {
throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
}
_accountMgr.checkAccess(caller, domain);
} else {
domain = _domainDao.findById(caller.getDomainId());
}
String domainPath = domain.getPath();
// search for groups
Pair<List<IAMGroup>, Integer> result = _iamSrv.listIAMGroups(iamGroupId, iamGroupName, domainPath, startIndex, pageSize);
// generate group response
ListResponse<IAMGroupResponse> response = new ListResponse<IAMGroupResponse>();
List<IAMGroupResponse> groupResponses = new ArrayList<IAMGroupResponse>();
for (IAMGroup group : result.first()) {
IAMGroupResponse resp = createIAMGroupResponse(group);
groupResponses.add(resp);
}
response.setResponses(groupResponses, result.second());
return response;
}
@Override
public ListResponse<IAMPolicyResponse> listIAMPolicies(Long iamPolicyId, String iamPolicyName, Long domainId, Long startIndex,
Long pageSize) {
// acl check
Account caller = CallContext.current().getCallingAccount();
Domain domain = null;
if (domainId != null) {
domain = _domainDao.findById(domainId);
if (domain == null) {
throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
}
_accountMgr.checkAccess(caller, domain);
} else {
domain = _domainDao.findById(caller.getDomainId());
}
String domainPath = domain.getPath();
// search for policies
Pair<List<IAMPolicy>, Integer> result = _iamSrv.listIAMPolicies(iamPolicyId, iamPolicyName, domainPath, startIndex, pageSize);
// generate policy response
ListResponse<IAMPolicyResponse> response = new ListResponse<IAMPolicyResponse>();
List<IAMPolicyResponse> policyResponses = new ArrayList<IAMPolicyResponse>();
for (IAMPolicy policy : result.first()) {
IAMPolicyResponse resp = createIAMPolicyResponse(policy);
policyResponses.add(resp);
}
response.setResponses(policyResponses, result.second());
return response;
}
@Override
public void grantEntityPermissioinToAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds) {
// check if there is already a policy with only this permission added to it
IAMPolicy policy = _iamSrv.getResourceGrantPolicy(entityType, entityId, accessType.toString(), action);
if (policy == null) {
// not found, just create a policy with resource grant permission
Account caller = CallContext.current().getCallingAccount();
String aclPolicyName = "policyGrant" + entityType + entityId;
String description = "Policy to grant permission to " + entityType + entityId;
policy = createIAMPolicy(caller, aclPolicyName, description, null);
// add permission to this policy
addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow, false);
}
// attach this policy to list of accounts if not attached already
Long policyId = policy.getId();
for (Long acctId : accountIds) {
if (!isPolicyAttachedToAccount(policyId, acctId)) {
attachIAMPolicyToAccounts(policyId, Collections.singletonList(acctId));
}
}
}
@Override
public void revokeEntityPermissioinFromAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds) {
// there should already a policy with only this permission added to it, this call is mainly used
IAMPolicy policy = _iamSrv.getResourceGrantPolicy(entityType, entityId, accessType.toString(), action);
if (policy == null) {
s_logger.warn("Cannot find a policy associated with this entity permissioin to be revoked, just return");
return;
}
// detach this policy from list of accounts if not detached already
Long policyId = policy.getId();
for (Long acctId : accountIds) {
if (isPolicyAttachedToAccount(policyId, acctId)) {
removeIAMPolicyFromAccounts(policyId, Collections.singletonList(acctId));
}
}
}
private boolean isPolicyAttachedToAccount(Long policyId, Long accountId) {
List<IAMPolicy> pList = listIAMPolicies(accountId);
for (IAMPolicy p : pList) {
if (p.getId() == policyId.longValue()) {
return true;
}
}
return false;
}
private void resetTemplatePermission(Long templateId){
// reset template will change template to private, so we need to remove its permission for domain admin and normal user group
_iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), templateId, "listTemplates");
_iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), templateId, "listTemplates");
// check if there is a policy with only UseEntry permission for this template added
IAMPolicy policy = _iamSrv.getResourceGrantPolicy(IAMEntityType.VirtualMachineTemplate.toString(), templateId, AccessType.UseEntry.toString(), "listTemplates");
if ( policy == null ){
s_logger.info("No policy found for this template grant: " + templateId + ", no detach to be done");
return;
}
// delete the policy, which should detach it from groups and accounts
_iamSrv.deleteIAMPolicy(policy.getId());
}
@Override
public Long getPermissionScopeId(String scope, String entityType, String scopeId) {
if (scopeId.equals("-1")) {
return -1L;
}
PermissionScope permScope = PermissionScope.valueOf(scope);
InternalIdentity entity = null;
switch (permScope) {
case DOMAIN:
entity = _domainDao.findByUuid(scopeId);
break;
case ACCOUNT:
entity = _accountDao.findByUuid(scopeId);
break;
case RESOURCE:
Class<?> clazz = s_typeMap.get(IAMEntityType.valueOf(entityType));
entity = (InternalIdentity)_entityMgr.findByUuid(clazz, scopeId);
}
if (entity != null) {
return entity.getId();
}
throw new InvalidParameterValueException("Unable to find scopeId " + scopeId + " with scope " + scope + " and type " + entityType);
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
cmdList.add(CreateIAMPolicyCmd.class);
cmdList.add(DeleteIAMPolicyCmd.class);
cmdList.add(ListIAMPoliciesCmd.class);
cmdList.add(AddIAMPermissionToIAMPolicyCmd.class);
cmdList.add(RemoveIAMPermissionFromIAMPolicyCmd.class);
cmdList.add(AttachIAMPolicyToIAMGroupCmd.class);
cmdList.add(RemoveIAMPolicyFromIAMGroupCmd.class);
cmdList.add(CreateIAMGroupCmd.class);
cmdList.add(DeleteIAMGroupCmd.class);
cmdList.add(ListIAMGroupsCmd.class);
cmdList.add(AddAccountToIAMGroupCmd.class);
cmdList.add(RemoveAccountFromIAMGroupCmd.class);
cmdList.add(AttachIAMPolicyToAccountCmd.class);
cmdList.add(RemoveIAMPolicyFromAccountCmd.class);
return cmdList;
}
}

View File

@ -0,0 +1,273 @@
// 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.iam;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.acl.IAMEntityType;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import org.apache.cloudstack.iam.api.IAMService;
import com.cloud.api.ApiServerService;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.exception.CloudRuntimeException;
//This is the Role Based API access checker that grab's the account's roles
//based on the set of roles, access is granted if any of the role has access to the api
@Local(value=APIChecker.class)
public class RoleBasedAPIAccessChecker extends AdapterBase implements APIChecker {
protected static final Logger s_logger = Logger.getLogger(RoleBasedAPIAccessChecker.class);
@Inject
AccountService _accountService;
@Inject
ApiServerService _apiServer;
@Inject
IAMService _iamSrv;
@Inject
VMTemplateDao _templateDao;
Set<String> commandsPropertiesOverrides = new HashSet<String>();
Map<RoleType, Set<String>> commandsPropertiesRoleBasedApisMap = new HashMap<RoleType, Set<String>>();
List<PluggableService> _services;
protected RoleBasedAPIAccessChecker() {
super();
for (RoleType roleType : RoleType.values()) {
commandsPropertiesRoleBasedApisMap.put(roleType, new HashSet<String>());
}
}
@Override
public boolean checkAccess(User user, String commandName) throws PermissionDeniedException {
Account account = _accountService.getAccount(user.getAccountId());
if (account == null) {
throw new PermissionDeniedException("The account id=" + user.getAccountId() + "for user id=" + user.getId()
+ "is null");
}
List<IAMPolicy> policies = _iamSrv.listIAMPolicies(account.getAccountId());
boolean isAllowed = _iamSrv.isActionAllowedForPolicies(commandName, policies);
if (!isAllowed) {
throw new PermissionDeniedException("The API does not exist or is blacklisted. api: " + commandName);
}
return isAllowed;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
processMapping(PropertiesUtil.processConfigFile(new String[] { "commands.properties" }));
return true;
}
@Override
public boolean start() {
// drop all default policy api permissions - we reload them every time
// to include any changes done to the @APICommand or
// commands.properties.
for (RoleType role : RoleType.values()) {
Long policyId = getDefaultPolicyId(role);
if (policyId != null) {
_iamSrv.resetIAMPolicy(policyId);
}
}
// add the system-domain capability
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_ADMIN + 1), null, null, null,
"SystemCapability", null, Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), null, null, null,
"DomainCapability", null, Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN + 1), null, null, null,
"DomainResourceCapability", null, Permission.Allow, false);
// add permissions for public templates
List<VMTemplateVO> pTmplts = _templateDao.listByPublic();
for (VMTemplateVO tmpl : pTmplts){
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(),
PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
}
for (PluggableService service : _services) {
for (Class<?> cmdClass : service.getCommands()) {
APICommand command = cmdClass.getAnnotation(APICommand.class);
if (!commandsPropertiesOverrides.contains(command.name())) {
for (RoleType role : command.authorized()) {
addDefaultAclPolicyPermission(command.name(), cmdClass, role);
}
}
}
}
// read commands.properties and load api acl permissions -
// commands.properties overrides any @APICommand authorization
for (String apiName : commandsPropertiesOverrides) {
Class<?> cmdClass = _apiServer.getCmdClass(apiName);
for (RoleType role : RoleType.values()) {
if (commandsPropertiesRoleBasedApisMap.get(role).contains(apiName)) {
// insert permission for this role for this api
addDefaultAclPolicyPermission(apiName, cmdClass, role);
}
}
}
return super.start();
}
private Long getDefaultPolicyId(RoleType role) {
Long policyId = null;
switch (role) {
case User:
policyId = new Long(Account.ACCOUNT_TYPE_NORMAL + 1);
break;
case Admin:
policyId = new Long(Account.ACCOUNT_TYPE_ADMIN + 1);
break;
case DomainAdmin:
policyId = new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1);
break;
case ResourceAdmin:
policyId = new Long(Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN + 1);
break;
}
return policyId;
}
private void processMapping(Map<String, String> configMap) {
for (Map.Entry<String, String> entry : configMap.entrySet()) {
String apiName = entry.getKey();
String roleMask = entry.getValue();
commandsPropertiesOverrides.add(apiName);
try {
short cmdPermissions = Short.parseShort(roleMask);
for (RoleType roleType : RoleType.values()) {
if ((cmdPermissions & roleType.getValue()) != 0)
commandsPropertiesRoleBasedApisMap.get(roleType).add(apiName);
}
} catch (NumberFormatException nfe) {
s_logger.info("Malformed key=value pair for entry: " + entry.toString());
}
}
}
public List<PluggableService> getServices() {
return _services;
}
@Inject
public void setServices(List<PluggableService> services) {
_services = services;
}
private void addDefaultAclPolicyPermission(String apiName, Class<?> cmdClass, RoleType role) {
AccessType accessType = null;
IAMEntityType[] entityTypes = null;
if (cmdClass != null) {
BaseCmd cmdObj;
try {
cmdObj = (BaseCmd) cmdClass.newInstance();
if (cmdObj instanceof BaseListCmd) {
accessType = AccessType.UseEntry;
} else if (!(cmdObj instanceof BaseAsyncCreateCmd)) {
accessType = AccessType.OperateEntry;
}
} catch (Exception e) {
throw new CloudRuntimeException(String.format(
"%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName()));
}
APICommand at = cmdClass.getAnnotation(APICommand.class);
entityTypes = at.entityType();
}
PermissionScope permissionScope = PermissionScope.ACCOUNT;
Long policyId = getDefaultPolicyId(role);
switch (role) {
case User:
permissionScope = PermissionScope.ACCOUNT;
break;
case Admin:
permissionScope = PermissionScope.ALL;
break;
case DomainAdmin:
permissionScope = PermissionScope.DOMAIN;
break;
case ResourceAdmin:
permissionScope = PermissionScope.DOMAIN;
break;
}
if (entityTypes == null || entityTypes.length == 0) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, null, permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER),
apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false);
} else {
for (IAMEntityType entityType : entityTypes) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.toString(), permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER),
apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false);
}
}
}
}

View File

@ -0,0 +1,186 @@
// 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.iam;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.InternalIdentity;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMService;
import com.cloud.acl.DomainChecker;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
public class RoleBasedEntityAccessChecker extends DomainChecker implements SecurityChecker {
private static final Logger s_logger = Logger.getLogger(RoleBasedEntityAccessChecker.class.getName());
@Inject
AccountService _accountService;
@Inject DomainDao _domainDao;
@Inject
IAMService _iamSrv;
@Override
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType)
throws PermissionDeniedException {
return checkAccess(caller, entity, accessType, null);
}
@Override
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action)
throws PermissionDeniedException {
if (entity == null && action != null) {
// check if caller can do this action
List<IAMPolicy> policies = _iamSrv.listIAMPolicies(caller.getAccountId());
boolean isAllowed = _iamSrv.isActionAllowedForPolicies(action, policies);
if (!isAllowed) {
throw new PermissionDeniedException("The action '" + action + "' not allowed for account " + caller);
}
return true;
}
String entityType = entity.getEntityType().toString();
if (accessType == null) {
accessType = AccessType.UseEntry;
}
// get all Policies of this caller w.r.t the entity
List<IAMPolicy> policies = getEffectivePolicies(caller, entity);
HashMap<IAMPolicy, Boolean> policyPermissionMap = new HashMap<IAMPolicy, Boolean>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> permissions = new ArrayList<IAMPolicyPermission>();
if (action != null) {
permissions = _iamSrv.listPolicyPermissionByActionAndEntity(policy.getId(), action, entityType);
if (permissions.isEmpty()) {
if (accessType != null) {
permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(),
accessType.toString(), entityType));
}
}
} else {
if (accessType != null) {
permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(),
accessType.toString(), entityType));
}
}
for (IAMPolicyPermission permission : permissions) {
if (checkPermissionScope(caller, permission.getScope(), permission.getScopeId(), entity)) {
if (permission.getEntityType().equals(entityType)) {
policyPermissionMap.put(policy, permission.getPermission().isGranted());
break;
} else if (permission.getEntityType().equals("*")) {
policyPermissionMap.put(policy, permission.getPermission().isGranted());
}
}
}
if (policyPermissionMap.containsKey(policy) && policyPermissionMap.get(policy)) {
return true;
}
}
if (!policies.isEmpty()) { // Since we reach this point, none of the
// roles granted access
if (s_logger.isDebugEnabled()) {
s_logger.debug("Account " + caller + " does not have permission to access resource " + entity
+ " for access type: " + accessType);
}
throw new PermissionDeniedException(caller + " does not have permission to access resource " + entity);
}
return false;
}
private boolean checkPermissionScope(Account caller, String scope, Long scopeId, ControlledEntity entity) {
if(scopeId != null && !scopeId.equals(new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER))){
//scopeId is set
if (scope.equals(PermissionScope.ACCOUNT.name())) {
if(scopeId == entity.getAccountId()){
return true;
}
} else if (scope.equals(PermissionScope.DOMAIN.name())) {
if (_domainDao.isChildDomain(scopeId, entity.getDomainId())) {
return true;
}
} else if (scope.equals(PermissionScope.RESOURCE.name())) {
if (entity instanceof InternalIdentity) {
InternalIdentity entityWithId = (InternalIdentity) entity;
if(scopeId.equals(entityWithId.getId())){
return true;
}
}
}
} else if (scopeId == null || scopeId.equals(new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER))) {
if (scope.equals(PermissionScope.ACCOUNT.name())) {
if(caller.getAccountId() == entity.getAccountId()){
return true;
}
} else if (scope.equals(PermissionScope.DOMAIN.name())) {
if (_domainDao.isChildDomain(caller.getDomainId(), entity.getDomainId())) {
return true;
}
}
}
return false;
}
private List<IAMPolicy> getEffectivePolicies(Account caller, ControlledEntity entity) {
// Get the static Policies of the Caller
List<IAMPolicy> policies = _iamSrv.listIAMPolicies(caller.getId());
// add any dynamic policies w.r.t the entity
if (caller.getId() == entity.getAccountId()) {
// The caller owns the entity
policies.add(_iamSrv.getResourceOwnerPolicy());
}
List<IAMGroup> groups = _iamSrv.listIAMGroups(caller.getId());
for (IAMGroup group : groups) {
// for each group find the grand parent groups.
List<IAMGroup> parentGroups = _iamSrv.listParentIAMGroups(group.getId());
for (IAMGroup parentGroup : parentGroups) {
policies.addAll(_iamSrv.listRecursiveIAMPoliciesByGroup(parentGroup.getId()));
}
}
return policies;
}
}

View File

@ -0,0 +1,147 @@
// 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.iam;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.QuerySelector;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMService;
import com.cloud.user.Account;
import com.cloud.utils.component.AdapterBase;
public class RoleBasedEntityQuerySelector extends AdapterBase implements QuerySelector {
private static final Logger s_logger = Logger.getLogger(RoleBasedEntityQuerySelector.class.getName());
@Inject
IAMService _iamService;
@Override
public List<Long> getAuthorizedDomains(Account caller, String action) {
long accountId = caller.getAccountId();
// Get the static Policies of the Caller
List<IAMPolicy> policies = _iamService.listIAMPolicies(accountId);
// for each policy, find granted permission with Domain scope
List<Long> domainIds = new ArrayList<Long>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.DOMAIN.toString());
if (pp != null) {
for (IAMPolicyPermission p : pp) {
if (p.getScopeId() != null) {
if (p.getScopeId().longValue() == -1) {
domainIds.add(caller.getDomainId());
} else {
domainIds.add(p.getScopeId());
}
}
}
}
}
return domainIds;
}
@Override
public List<Long> getAuthorizedAccounts(Account caller, String action) {
long accountId = caller.getAccountId();
// Get the static Policies of the Caller
List<IAMPolicy> policies = _iamService.listIAMPolicies(accountId);
// for each policy, find granted permission with Account scope
List<Long> accountIds = new ArrayList<Long>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ACCOUNT.toString());
if (pp != null) {
for (IAMPolicyPermission p : pp) {
if (p.getScopeId() != null) {
if (p.getScopeId().longValue() == -1) {
accountIds.add(caller.getId());
} else {
accountIds.add(p.getScopeId());
}
}
}
}
}
return accountIds;
}
@Override
public List<Long> getAuthorizedResources(Account caller, String action) {
long accountId = caller.getAccountId();
// Get the static Policies of the Caller
List<IAMPolicy> policies = _iamService.listIAMPolicies(accountId);
// add the policies that grant recursive access
List<IAMGroup> groups = _iamService.listIAMGroups(caller.getId());
for (IAMGroup group : groups) {
// for each group find the grand parent groups.
List<IAMGroup> parentGroups = _iamService.listParentIAMGroups(group.getId());
for (IAMGroup parentGroup : parentGroups) {
policies.addAll(_iamService.listRecursiveIAMPoliciesByGroup(parentGroup.getId()));
}
}
// for each policy, find granted permission with Resource scope
List<Long> entityIds = new ArrayList<Long>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.RESOURCE.toString());
if (pp != null) {
for (IAMPolicyPermission p : pp) {
if (p.getScopeId() != null) {
entityIds.add(p.getScopeId());
}
}
}
}
return entityIds;
}
@Override
public boolean isGrantedAll(Account caller, String action) {
long accountId = caller.getAccountId();
// Get the static Policies of the Caller
List<IAMPolicy> policies = _iamService.listIAMPolicies(accountId);
// for each policy, find granted permission with ALL scope
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ALL.toString());
if (pp != null && pp.size() > 0) {
return true;
}
}
return false;
}
@Override
public List<String> listAclGroupsByAccount(long accountId) {
List<IAMGroup> groups = _iamService.listIAMGroups(accountId);
List<String> groupNames = new ArrayList<String>();
for (IAMGroup grp : groups) {
groupNames.add(grp.getName());
}
return groupNames;
}
}

View File

@ -0,0 +1,369 @@
package org.apache.cloudstack.iam.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.apache.cloudstack.acl.IAMEntityType;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.iam.IAMGroupResponse;
import org.apache.cloudstack.api.response.iam.IAMPermissionResponse;
import org.apache.cloudstack.api.response.iam.IAMPolicyResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.iam.IAMApiService;
import org.apache.cloudstack.iam.IAMApiServiceImpl;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import org.apache.cloudstack.iam.api.IAMService;
import org.apache.cloudstack.iam.server.IAMGroupVO;
import org.apache.cloudstack.iam.server.IAMPolicyPermissionVO;
import org.apache.cloudstack.iam.server.IAMPolicyVO;
import org.apache.cloudstack.test.utils.SpringUtils;
import com.cloud.api.ApiServerService;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.db.EntityManager;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class IAMApiServiceTest {
@Inject
IAMService _iamSrv;
@Inject
DomainDao _domainDao;
@Inject
IAMApiService _aclSrv;
@Inject
AccountManager _accountMgr;
@Inject
AccountDao _accountDao;
@Inject
ApiServerService _apiServer;
private static Account caller;
private static Long callerId;
private static String callerAccountName = "tester";
private static Long callerDomainId = 3L;
private static String callerDomainPath = "/root/testdomain";
private static DomainVO callerDomain;
@BeforeClass
public static void setUpClass() throws ConfigurationException {
}
@Before
public void setUp() {
ComponentContext.initComponentsLifeCycle();
caller = new AccountVO(callerAccountName, callerDomainId, null, Account.ACCOUNT_TYPE_ADMIN, UUID.randomUUID().toString());
callerId = caller.getId();
callerDomain = new DomainVO();
callerDomain.setPath(callerDomainPath);
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString());
CallContext.register(user, caller);
when(_domainDao.findById(callerDomainId)).thenReturn(callerDomain);
doNothing().when(_accountMgr).checkAccess(caller, callerDomain);
}
@Test
public void createIAMGroupTest() {
IAMGroup group = new IAMGroupVO("group1", "tester group1");
List<IAMGroup> groups = new ArrayList<IAMGroup>();
groups.add(group);
Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1);
when(_iamSrv.createIAMGroup("group1", "tester group1", callerDomainPath)).thenReturn(group);
when(_iamSrv.listIAMGroups(null, null, callerDomainPath, 0L, 20L)).thenReturn(grpList);
IAMGroup createdGrp = _aclSrv.createIAMGroup(caller, "group1", "tester group1");
assertNotNull("IAM group 'group1' failed to create ", createdGrp);
ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, null, callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", grpResp.getCount() == 1);
IAMGroupResponse resp = grpResp.getResponses().get(0);
assertEquals("Error in created group name", "group1", resp.getName());
}
@Test
public void deleteIAMGroupTest() {
when(_iamSrv.deleteIAMGroup(1L)).thenReturn(true);
assertTrue("failed to delete acl group 1", _aclSrv.deleteIAMGroup(1L));
}
@Test
public void listIAMGroupTest() {
IAMGroup group = new IAMGroupVO("group1", "tester group1");
List<IAMGroup> groups = new ArrayList<IAMGroup>();
groups.add(group);
when(_iamSrv.listIAMGroups(callerId)).thenReturn(groups);
List<IAMGroup> grps = _aclSrv.listIAMGroups(callerId);
assertTrue(grps != null && grps.size() == 1);
IAMGroup grp = grps.get(0);
assertEquals("Error to retrieve group", "group1", grp.getName());
}
@Test
public void addRemoveAccountToGroupTest() {
IAMGroup group = new IAMGroupVO("group1", "tester group1");
List<IAMGroup> groups = new ArrayList<IAMGroup>();
groups.add(group);
Long groupId = group.getId();
List<Long> acctIds = new ArrayList<Long>();
AccountVO acct1 = new AccountVO(100L);
acct1.setAccountName("account1");
AccountVO acct2 = new AccountVO(200L);
acct2.setAccountName("account2");
acctIds.add(acct1.getId());
acctIds.add(acct2.getId());
when(_accountDao.findById(acct1.getId())).thenReturn(acct1);
when(_accountDao.findById(acct2.getId())).thenReturn(acct2);
when(_iamSrv.addAccountsToGroup(acctIds, groupId)).thenReturn(group);
when(_iamSrv.listAccountsByGroup(groupId)).thenReturn(acctIds);
Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1);
when(_iamSrv.listIAMGroups(null, "group1", callerDomainPath, 0L, 20L)).thenReturn(grpList);
_aclSrv.addAccountsToGroup(acctIds, groupId);
ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", grpResp.getCount() == 1);
IAMGroupResponse resp = grpResp.getResponses().get(0);
Set<String> acctNames = resp.getAccountNameList();
assertEquals("There should be 2 accounts in the group", 2, acctNames.size());
assertTrue("account1 should be assigned to the group", acctNames.contains("account1"));
assertTrue("account2 should be assigned to the group", acctNames.contains("account2"));
// remove "account2" from group1
acctIds.remove(1);
List<Long> rmAccts = new ArrayList<Long>();
rmAccts.add(acct2.getId());
when(_iamSrv.removeAccountsFromGroup(rmAccts, groupId)).thenReturn(group);
_aclSrv.removeAccountsFromGroup(acctIds, groupId);
grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", grpResp.getCount() == 1);
resp = grpResp.getResponses().get(0);
acctNames = resp.getAccountNameList();
assertEquals("There should be 1 accounts in the group", 1, acctNames.size());
assertFalse("account2 should not belong to the group anymore", acctNames.contains("account2"));
}
@Test
public void createIAMPolicyTest() {
IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1");
List<IAMPolicy> policies = new ArrayList<IAMPolicy>();
policies.add(policy);
Pair<List<IAMPolicy>, Integer> policyList = new Pair<List<IAMPolicy>, Integer>(policies, 1);
when(_iamSrv.createIAMPolicy("policy1", "tester policy1", null, callerDomainPath)).thenReturn(policy);
when(_iamSrv.listIAMPolicies(null, null, callerDomainPath, 0L, 20L)).thenReturn(policyList);
IAMPolicy createdPolicy = _aclSrv.createIAMPolicy(caller, "policy1", "tester policy1", null);
assertNotNull("IAM policy 'policy1' failed to create ", createdPolicy);
ListResponse<IAMPolicyResponse> policyResp = _aclSrv.listIAMPolicies(null, null, callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", policyResp.getCount() == 1);
IAMPolicyResponse resp = policyResp.getResponses().get(0);
assertEquals("Error in created group name", "policy1", resp.getName());
}
@Test
public void deleteIAMPolicyTest() {
when(_iamSrv.deleteIAMPolicy(1L)).thenReturn(true);
assertTrue("failed to delete acl policy 1", _aclSrv.deleteIAMPolicy(1L));
}
@Test
public void listIAMPolicyTest() {
IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1");
List<IAMPolicy> policies = new ArrayList<IAMPolicy>();
policies.add(policy);
when(_iamSrv.listIAMPolicies(callerId)).thenReturn(policies);
List<IAMPolicy> polys = _aclSrv.listIAMPolicies(callerId);
assertTrue(polys != null && polys.size() == 1);
IAMPolicy p = polys.get(0);
assertEquals("Error to retrieve group", "policy1", p.getName());
}
@Test
public void addRemovePolicyToGroupTest() {
IAMGroup group = new IAMGroupVO("group1", "tester group1");
List<IAMGroup> groups = new ArrayList<IAMGroup>();
groups.add(group);
Long groupId = group.getId();
List<Long> policyIds = new ArrayList<Long>();
policyIds.add(100L);
policyIds.add(200L);
IAMPolicy policy1 = new IAMPolicyVO("policy1", "my first policy");
IAMPolicy policy2 = new IAMPolicyVO("policy2", "my second policy");
List<IAMPolicy> policies = new ArrayList<IAMPolicy>();
policies.add(policy1);
policies.add(policy2);
when(_iamSrv.attachIAMPoliciesToGroup(policyIds, groupId)).thenReturn(group);
when(_iamSrv.listIAMPoliciesByGroup(groupId)).thenReturn(policies);
Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1);
when(_iamSrv.listIAMGroups(null, "group1", callerDomainPath, 0L, 20L)).thenReturn(grpList);
_aclSrv.attachIAMPoliciesToGroup(policyIds, groupId);
ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", grpResp.getCount() == 1);
IAMGroupResponse resp = grpResp.getResponses().get(0);
Set<String> policyNames = resp.getPolicyList();
assertEquals("There should be 2 policies in the group", 2, policyNames.size());
assertTrue("policy1 should be assigned to the group", policyNames.contains("policy1"));
assertTrue("policy2 should be assigned to the group", policyNames.contains("policy2"));
// remove "policy2" from group1
policyIds.remove(1);
policies.remove(policy2);
when(_iamSrv.removeIAMPoliciesFromGroup(policyIds, groupId)).thenReturn(group);
_aclSrv.removeIAMPoliciesFromGroup(policyIds, groupId);
grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", grpResp.getCount() == 1);
resp = grpResp.getResponses().get(0);
policyNames = resp.getPolicyList();
assertEquals("There should be 1 policy attached to the group", 1, policyNames.size());
assertFalse("policy2 should not belong to the group anymore", policyNames.contains("policy2"));
}
@Test
public void addRemovePermissionToPolicyTest() {
IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1");
List<IAMPolicy> policies = new ArrayList<IAMPolicy>();
policies.add(policy);
Long policyId = policy.getId();
Long resId = 200L;
Class clz = ListVMsCmd.class;
when(_apiServer.getCmdClass("listVirtualMachines")).thenReturn(clz);
when(
_iamSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(),
PermissionScope.RESOURCE.toString(), resId, "listVirtualMachines",
AccessType.UseEntry.toString(), Permission.Allow, false)).thenReturn(policy);
_aclSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(),
PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false);
Pair<List<IAMPolicy>, Integer> policyList = new Pair<List<IAMPolicy>, Integer>(policies, 1);
List<IAMPolicyPermission> policyPerms = new ArrayList<IAMPolicyPermission>();
IAMPolicyPermission perm = new IAMPolicyPermissionVO(policyId, "listVirtualMachines",
IAMEntityType.VirtualMachine.toString(), AccessType.UseEntry.toString(),
PermissionScope.RESOURCE.toString(),
resId, Permission.Allow, false);
policyPerms.add(perm);
when(_iamSrv.listIAMPolicies(null, "policy1", callerDomainPath, 0L, 20L)).thenReturn(policyList);
when(_iamSrv.listPolicyPermissions(policyId)).thenReturn(policyPerms);
ListResponse<IAMPolicyResponse> policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", policyResp.getCount() == 1);
IAMPolicyResponse resp = policyResp.getResponses().get(0);
Set<IAMPermissionResponse> permList = resp.getPermissionList();
assertTrue("Permission list should not be empty", permList != null && permList.size() > 0);
IAMPermissionResponse permResp = permList.iterator().next();
assertEquals("There should be one permission for listVirtualMachines", "listVirtualMachines", permResp.getAction());
//remove permission from policy
policyPerms.remove(perm);
_aclSrv.removeIAMPermissionFromIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(),
PermissionScope.RESOURCE, resId, "listVirtualMachines");
policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L);
assertTrue("No. of response items should be one", policyResp.getCount() == 1);
resp = policyResp.getResponses().get(0);
permList = resp.getPermissionList();
assertTrue("Permission list should be empty", permList != null && permList.size() == 0);
}
@After
public void tearDown() {
}
@Configuration
@ComponentScan(basePackageClasses = {IAMApiServiceImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false)
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
@Bean
public DomainDao domainDao() {
return Mockito.mock(DomainDao.class);
}
@Bean
public IAMService iamService() {
return Mockito.mock(IAMService.class);
}
@Bean
public AccountDao accountDao() {
return Mockito.mock(AccountDao.class);
}
@Bean
public NetworkDomainDao networkDomainDao() {
return Mockito.mock(NetworkDomainDao.class);
}
@Bean
public AccountManager accountManager() {
return Mockito.mock(AccountManager.class);
}
@Bean
public MessageBus messageBus() {
return Mockito.mock(MessageBus.class);
}
@Bean
public EntityManager entityMgr() {
return Mockito.mock(EntityManager.class);
}
@Bean
public ApiServerService apiServerService() {
return Mockito.mock(ApiServerService.class);
}
public static class Library implements TypeFilter {
@Override
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
}
}
}
}

View File

@ -0,0 +1,75 @@
# 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.
# management server clustering parameters, change cluster.node.IP to the machine IP address
# in which the management server(Tomcat) is running
cluster.node.IP=127.0.0.1
cluster.servlet.port=9090
region.id=1
# CloudStack database settings
db.cloud.username=cloud
db.cloud.password=cloud
db.root.password=
db.cloud.host=localhost
db.cloud.port=3306
db.cloud.name=cloud
# CloudStack database tuning parameters
db.cloud.maxActive=250
db.cloud.maxIdle=30
db.cloud.maxWait=10000
db.cloud.autoReconnect=true
db.cloud.validationQuery=SELECT 1
db.cloud.testOnBorrow=true
db.cloud.testWhileIdle=true
db.cloud.timeBetweenEvictionRunsMillis=40000
db.cloud.minEvictableIdleTimeMillis=240000
db.cloud.poolPreparedStatements=false
db.cloud.url.params=prepStmtCacheSize=517&cachePrepStmts=true&prepStmtCacheSqlLimit=4096
# usage database settings
db.usage.username=cloud
db.usage.password=cloud
db.usage.host=localhost
db.usage.port=3306
db.usage.name=cloud_usage
# usage database tuning parameters
db.usage.maxActive=100
db.usage.maxIdle=30
db.usage.maxWait=10000
db.usage.autoReconnect=true
# awsapi database settings
db.awsapi.username=cloud
db.awsapi.password=cloud
db.awsapi.host=localhost
db.awsapi.port=3306
db.awsapi.name=cloudbridge
# Simulator database settings
db.simulator.username=cloud
db.simulator.password=cloud
db.simulator.host=localhost
db.simulator.port=3306
db.simulator.name=simulator
db.simulator.maxActive=250
db.simulator.maxIdle=30
db.simulator.maxWait=10000
db.simulator.autoReconnect=true