diff --git a/services/iam/server/pom.xml b/services/iam/server/pom.xml
new file mode 100644
index 00000000000..bed8811d168
--- /dev/null
+++ b/services/iam/server/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+ cloud-iam
+ Apache CloudStack IAM - Server
+
+ org.apache.cloudstack
+ cloudstack-service-iam
+ 4.4.0-SNAPSHOT
+ ../pom.xml
+
+
+
+ commons-io
+ commons-io
+
+
+ org.apache.cloudstack
+ cloud-utils
+ ${project.version}
+
+
+ org.apache.cloudstack
+ cloud-api
+ ${project.version}
+
+
+ org.apache.cloudstack
+ cloud-api
+ ${project.version}
+ test-jar
+ test
+
+
+
diff --git a/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml b/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml
new file mode 100644
index 00000000000..c9f383f4f54
--- /dev/null
+++ b/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMGroup.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMGroup.java
new file mode 100644
index 00000000000..868d0a0d449
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMGroup.java
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface IAMGroup extends InternalIdentity, Identity {
+
+ String getName();
+
+ String getDescription();
+
+ @Override
+ long getId();
+
+ @Override
+ String getUuid();
+
+ String getPath();
+
+ long getAccountId();
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicy.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicy.java
new file mode 100644
index 00000000000..e6daeb11c68
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicy.java
@@ -0,0 +1,41 @@
+// 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.api;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface IAMPolicy extends InternalIdentity, Identity {
+
+ String getName();
+
+ String getDescription();
+
+ public enum PolicyType {
+ Static, Dynamic
+ }
+
+ @Override
+ long getId();
+
+ @Override
+ String getUuid();
+
+ String getPath();
+
+ long getAccountId();
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicyPermission.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicyPermission.java
new file mode 100644
index 00000000000..b91086fc869
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMPolicyPermission.java
@@ -0,0 +1,53 @@
+// 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.api;
+
+
+public interface IAMPolicyPermission {
+
+ String getAction();
+
+ long getAclPolicyId();
+
+ String getEntityType();
+
+ String getAccessType();
+
+ String getScope();
+
+ Long getScopeId();
+
+ Permission getPermission();
+
+ public enum Permission {
+ Allow(true), Deny(false);
+
+ boolean result;
+
+ Permission(boolean result) {
+ this.result = result;
+ }
+
+ public boolean isGranted() {
+ return result;
+ }
+ }
+
+ long getId();
+
+ public static final long PERMISSION_SCOPE_ID_CURRENT_CALLER = -1;
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
new file mode 100644
index 00000000000..74a08851506
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
@@ -0,0 +1,92 @@
+// 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.api;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
+
+import com.cloud.utils.Pair;
+
+public interface IAMService {
+
+ /* IAM group related interfaces */
+ IAMGroup createIAMGroup(String iamGroupName, String description, String path);
+
+ boolean deleteIAMGroup(Long iamGroupId);
+
+ List listIAMGroups(long accountId);
+
+ IAMGroup addAccountsToGroup(List acctIds, Long groupId);
+
+ IAMGroup removeAccountsFromGroup(List acctIds, Long groupId);
+
+ List listAccountsByGroup(long groupId);
+
+ Pair, Integer> listIAMGroups(Long iamGroupId, String iamGroupName, String path, Long startIndex, Long pageSize);
+
+ /* IAM Policy related interfaces */
+ IAMPolicy createIAMPolicy(String iamPolicyName, String description, Long parentPolicyId, String path);
+
+ boolean deleteIAMPolicy(long iamPolicyId);
+
+ List listIAMPolicies(long accountId);
+
+ List listIAMPoliciesByGroup(long groupId);
+
+ Pair, Integer> listIAMPolicies(Long iamPolicyId, String iamPolicyName, String path, Long startIndex, Long pageSize);
+
+ IAMGroup attachIAMPoliciesToGroup(List policyIds, Long groupId);
+
+ IAMGroup removeIAMPoliciesFromGroup(List policyIds, Long groupId);
+
+ void attachIAMPolicyToAccounts(Long policyId, List acctIds);
+
+ void removeIAMPolicyFromAccounts(Long policyId, List acctIds);
+
+ IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
+ String action, String accessType, Permission perm, Boolean recursive);
+
+ IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
+ String action);
+
+ void removeIAMPermissionForEntity(final String entityType, final Long entityId);
+
+ IAMPolicy getResourceGrantPolicy(String entityType, Long entityId, String accessType, String action);
+
+ IAMPolicy getResourceOwnerPolicy();
+
+ List listPolicyPermissions(long policyId);
+
+ List listPolicyPermissionsByScope(long policyId, String action, String scope);
+
+ List listPolicyPermissionByActionAndEntity(long policyId, String action, String entityType);
+
+ boolean isActionAllowedForPolicies(String action, List policies);
+
+ List getGrantedEntities(long accountId, String action, String scope);
+
+ IAMPolicy resetIAMPolicy(long iamPolicyId);
+
+ List listPolicyPermissionByAccessAndEntity(long policyId, String accessType,
+ String entityType);
+
+ List listParentIAMGroups(long groupId);
+
+ List listRecursiveIAMPoliciesByGroup(long groupId);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMAccountPolicyMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMAccountPolicyMapVO.java
new file mode 100644
index 00000000000..18f085a28fd
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMAccountPolicyMapVO.java
@@ -0,0 +1,77 @@
+// 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.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_account_policy_map"))
+public class IAMAccountPolicyMapVO {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = "policy_id")
+ private long iamPolicyId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public IAMAccountPolicyMapVO() {
+ }
+
+ public IAMAccountPolicyMapVO(long accountId, long iamPolicyId) {
+ this.accountId = accountId;
+ this.iamPolicyId = iamPolicyId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public long getIamPolicyId() {
+ return iamPolicyId;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupAccountMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupAccountMapVO.java
new file mode 100644
index 00000000000..dac7d35ef67
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupAccountMapVO.java
@@ -0,0 +1,78 @@
+// 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.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_group_account_map"))
+public class IAMGroupAccountMapVO {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "group_id")
+ private long aclGroupId;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public IAMGroupAccountMapVO() {
+ }
+
+ public IAMGroupAccountMapVO(long aclGroupId, long accountId) {
+ this.aclGroupId = aclGroupId;
+ this.accountId = accountId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAclGroupId() {
+ return aclGroupId;
+ }
+
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupPolicyMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupPolicyMapVO.java
new file mode 100644
index 00000000000..946d1f796a2
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupPolicyMapVO.java
@@ -0,0 +1,79 @@
+// 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.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_group_policy_map"))
+public class IAMGroupPolicyMapVO {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "group_id")
+ private long aclGroupId;
+
+ @Column(name = "policy_id")
+ private long aclPolicyId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public IAMGroupPolicyMapVO() {
+ }
+
+ public IAMGroupPolicyMapVO(long aclGroupId, long aclPolicyId) {
+ this.aclGroupId = aclGroupId;
+ this.aclPolicyId = aclPolicyId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAclGroupId() {
+ return aclGroupId;
+ }
+
+
+ public long getAclPolicyId() {
+ return aclPolicyId;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupVO.java
new file mode 100644
index 00000000000..80edb8977a7
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMGroupVO.java
@@ -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.iam.server;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.IAMGroup;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_group"))
+public class IAMGroupVO implements IAMGroup {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "path")
+ private String path;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public IAMGroupVO() {
+ uuid = UUID.randomUUID().toString();
+ }
+
+ public IAMGroupVO(String name, String description) {
+ this.name = name;
+ this.description = description;
+ uuid = UUID.randomUUID().toString();
+ path = "/";
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long acctId) {
+ accountId = acctId;
+ }
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyPermissionVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyPermissionVO.java
new file mode 100644
index 00000000000..13d6b814e53
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyPermissionVO.java
@@ -0,0 +1,181 @@
+// 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.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.IAMPolicyPermission;
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_policy_permission"))
+public class IAMPolicyPermissionVO implements IAMPolicyPermission {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "policy_id")
+ private long aclPolicyId;
+
+ @Column(name = "action")
+ private String action;
+
+ @Column(name = "resource_type")
+ private String entityType;
+
+ @Column(name = "access_type")
+ private String accessType;
+
+ @Column(name = "scope")
+ private String scope;
+
+ @Column(name = "scope_id")
+ private Long scopeId;
+
+ @Column(name = "permission")
+ @Enumerated(value = EnumType.STRING)
+ private Permission permission;
+
+ @Column(name = "recursive")
+ private Boolean recursive;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public IAMPolicyPermissionVO() {
+
+ }
+
+ public IAMPolicyPermissionVO(long aclPolicyId, String action, String entityType, String accessType, String scope,
+ Long scopeId, Permission permission, Boolean recursive) {
+ this.aclPolicyId = aclPolicyId;
+ this.action = action;
+ this.entityType = entityType;
+ this.accessType = accessType;
+ this.scope = scope;
+ this.scopeId = scopeId;
+ this.permission = permission;
+ this.recursive = recursive;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public long getAclPolicyId() {
+ return aclPolicyId;
+ }
+
+
+ public void setAclPolicyId(long aclPolicyId) {
+ this.aclPolicyId = aclPolicyId;
+ }
+
+ @Override
+ public String getEntityType() {
+ return entityType;
+ }
+
+ @Override
+ public String getAccessType() {
+ return accessType;
+ }
+
+
+ public void setEntityType(String entityType) {
+ this.entityType = entityType;
+ }
+
+ public void setAccessType(String accessType) {
+ this.accessType = accessType;
+ }
+
+ @Override
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+
+ @Override
+ public String getAction() {
+ return action;
+ }
+
+ @Override
+ public Long getScopeId() {
+ // TODO
+ // handle special -1 scopeId, current caller domain, account
+ /*
+ * if ( scopeId < 0 ){ Account caller =
+ * CallContext.current().getCallingAccount(); if ( scope ==
+ * PermissionScope.DOMAIN){ return caller.getDomainId(); } else if
+ * (scope == PermissionScope.ACCOUNT) { return caller.getAccountId(); }
+ * }
+ */
+ return scopeId;
+ }
+
+ @Override
+ public Permission getPermission() {
+ return permission;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public void setScopeId(Long scopeId) {
+ this.scopeId = scopeId;
+ }
+
+ public void setPermission(Permission permission) {
+ this.permission = permission;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public Boolean isRecursive() {
+ return recursive;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyVO.java
new file mode 100644
index 00000000000..25ebd011f39
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMPolicyVO.java
@@ -0,0 +1,138 @@
+// 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.server;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.IAMPolicy;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("iam_policy"))
+public class IAMPolicyVO implements IAMPolicy {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "path")
+ private String path;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ @Column(name = "policy_type")
+ @Enumerated(value = EnumType.STRING)
+ private IAMPolicy.PolicyType policyType;
+
+ public IAMPolicyVO() {
+ uuid = UUID.randomUUID().toString();
+ }
+
+ public IAMPolicyVO(String name, String description) {
+ this.name = name;
+ this.description = description;
+ uuid = UUID.randomUUID().toString();
+ policyType = IAMPolicy.PolicyType.Static;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long accountId) {
+ this.accountId = accountId;
+ }
+
+ public IAMPolicy.PolicyType getPolicyType() {
+ return policyType;
+ }
+
+ public void setPolicyType(IAMPolicy.PolicyType policyType) {
+ this.policyType = policyType;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
new file mode 100644
index 00000000000..097d84f958c
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
@@ -0,0 +1,815 @@
+// 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.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.PermissionScope;
+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.dao.IAMAccountPolicyMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupAccountMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupPolicyMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMPolicyDao;
+import org.apache.cloudstack.iam.server.dao.IAMPolicyPermissionDao;
+
+import com.cloud.exception.InvalidParameterValueException;
+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.utils.db.Filter;
+import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.JoinBuilder;
+import com.cloud.utils.db.JoinBuilder.JoinType;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
+
+@Local(value = {IAMService.class})
+public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
+
+ public static final Logger s_logger = Logger.getLogger(IAMServiceImpl.class);
+ private String _name;
+
+ @Inject
+ IAMPolicyDao _aclPolicyDao;
+
+ @Inject
+ IAMGroupDao _aclGroupDao;
+
+ @Inject
+ EntityManager _entityMgr;
+
+ @Inject
+ IAMGroupPolicyMapDao _aclGroupPolicyMapDao;
+
+ @Inject
+ IAMAccountPolicyMapDao _aclAccountPolicyMapDao;
+
+ @Inject
+ IAMGroupAccountMapDao _aclGroupAccountMapDao;
+
+ @Inject
+ IAMPolicyPermissionDao _policyPermissionDao;
+
+ @DB
+ @Override
+ public IAMGroup createIAMGroup(String iamGroupName, String description, String path) {
+ // check if the group is already existing
+ IAMGroup grp = _aclGroupDao.findByName(path, iamGroupName);
+ if (grp != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl group with name " + iamGroupName
+ + " already exisits for path " + path);
+ }
+ IAMGroupVO rvo = new IAMGroupVO(iamGroupName, description);
+ rvo.setPath(path);
+
+ return _aclGroupDao.persist(rvo);
+ }
+
+ @DB
+ @Override
+ public boolean deleteIAMGroup(final Long iamGroupId) {
+ // get the Acl Group entity
+ final IAMGroup grp = _aclGroupDao.findById(iamGroupId);
+ if (grp == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + iamGroupId
+ + "; failed to delete acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this group related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByGroupId(grp.getId());
+ if (groupPolicyMap != null) {
+ for (IAMGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this group related entry in acl_group_account table
+ List groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
+ if (groupAcctMap != null) {
+ for (IAMGroupAccountMapVO grpAcct : groupAcctMap) {
+ _aclGroupAccountMapDao.remove(grpAcct.getId());
+ }
+ }
+
+ // remove this group from acl_group table
+ _aclGroupDao.remove(iamGroupId);
+ }
+ });
+
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listIAMGroups(long accountId) {
+
+ GenericSearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class);
+ groupSB.selectFields(groupSB.entity().getAclGroupId());
+ groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
+ SearchCriteria groupSc = groupSB.create();
+ groupSc.setParameters("account", accountId);
+
+ List groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null);
+
+ SearchBuilder sb = _aclGroupDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", groupIds.toArray(new Object[groupIds.size()]));
+ @SuppressWarnings("rawtypes")
+ List groups = _aclGroupDao.search(sc, null);
+ return groups;
+ }
+
+ @DB
+ @Override
+ public IAMGroup addAccountsToGroup(final List acctIds, final Long groupId) {
+ // get the Acl Group entity
+ IAMGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add accounts to acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_account_map table
+ for (Long acctId : acctIds) {
+ // check account permissions
+ IAMGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap == null) {
+ // not there already
+ grMap = new IAMGroupAccountMapVO(groupId, acctId);
+ _aclGroupAccountMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @DB
+ @Override
+ public IAMGroup removeAccountsFromGroup(final List acctIds, final Long groupId) {
+ // get the Acl Group entity
+ IAMGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove accounts from acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entries from acl_group_account_map table
+ for (Long acctId : acctIds) {
+ IAMGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupAccountMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @Override
+ public List listAccountsByGroup(long groupId) {
+ List grpAcctMap = _aclGroupAccountMapDao.listByGroupId(groupId);
+ if (grpAcctMap == null || grpAcctMap.size() == 0) {
+ return new ArrayList();
+ }
+
+ List accts = new ArrayList();
+ for (IAMGroupAccountMapVO grpAcct : grpAcctMap) {
+ accts.add(grpAcct.getAccountId());
+ }
+ return accts;
+ }
+
+ @Override
+ public Pair, Integer> listIAMGroups(Long iamGroupId, String iamGroupName, String path, Long startIndex, Long pageSize) {
+ if (iamGroupId != null) {
+ IAMGroup group = _aclGroupDao.findById(iamGroupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group by id " + iamGroupId);
+ }
+ }
+
+ Filter searchFilter = new Filter(IAMGroupVO.class, "id", true, startIndex, pageSize);
+
+ SearchBuilder sb = _aclGroupDao.createSearchBuilder();
+ sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
+ sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
+ sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
+
+ SearchCriteria sc = sb.create();
+
+ if (iamGroupName != null) {
+ sc.setParameters("name", iamGroupName);
+ }
+
+ if (iamGroupId != null) {
+ sc.setParameters("id", iamGroupId);
+ }
+
+ sc.setParameters("path", path + "%");
+
+ Pair, Integer> groups = _aclGroupDao.searchAndCount(sc, searchFilter);
+ return new Pair, Integer>(new ArrayList(groups.first()), groups.second());
+ }
+
+ @Override
+ public List listParentIAMGroups(long groupId) {
+ IAMGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group by id " + groupId);
+ }
+
+ String path = group.getPath();
+ List pathList = new ArrayList();
+
+ String[] parts = path.split("/");
+
+ for (String part : parts) {
+ int start = path.indexOf(part);
+ if (start > 0) {
+ String subPath = path.substring(0, start);
+ pathList.add(subPath);
+ }
+ }
+
+ if (pathList.isEmpty()) {
+ return new ArrayList();
+ }
+
+ SearchBuilder sb = _aclGroupDao.createSearchBuilder();
+ sb.and("paths", sb.entity().getPath(), SearchCriteria.Op.IN);
+
+ SearchCriteria sc = sb.create();
+ sc.setParameters("paths", pathList.toArray());
+
+ List groups = _aclGroupDao.search(sc, null);
+
+ return new ArrayList(groups);
+
+ }
+
+ @DB
+ @Override
+ public IAMPolicy createIAMPolicy(final String iamPolicyName, final String description, final Long parentPolicyId, final String path) {
+
+ // check if the policy is already existing
+ IAMPolicy ro = _aclPolicyDao.findByName(iamPolicyName);
+ if (ro != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl policy with name " + iamPolicyName
+ + " already exisits");
+ }
+
+ IAMPolicy role = Transaction.execute(new TransactionCallback() {
+ @Override
+ public IAMPolicy doInTransaction(TransactionStatus status) {
+ IAMPolicyVO rvo = new IAMPolicyVO(iamPolicyName, description);
+ rvo.setPath(path);
+
+ IAMPolicy role = _aclPolicyDao.persist(rvo);
+ if (parentPolicyId != null) {
+ // copy parent role permissions
+ List perms = _policyPermissionDao.listByPolicy(parentPolicyId);
+ if (perms != null) {
+ for (IAMPolicyPermissionVO perm : perms) {
+ perm.setAclPolicyId(role.getId());
+ _policyPermissionDao.persist(perm);
+ }
+ }
+ }
+ return role;
+ }
+ });
+
+
+ return role;
+ }
+
+ @DB
+ @Override
+ public boolean deleteIAMPolicy(final long iamPolicyId) {
+ // get the Acl Policy entity
+ final IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ + "; failed to delete acl policy.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this role related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByPolicyId(policy.getId());
+ if (groupPolicyMap != null) {
+ for (IAMGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this policy related entry in acl_account_policy_map table
+ List policyAcctMap = _aclAccountPolicyMapDao.listByPolicyId(policy.getId());
+ if (policyAcctMap != null) {
+ for (IAMAccountPolicyMapVO policyAcct : policyAcctMap) {
+ _aclAccountPolicyMapDao.remove(policyAcct.getId());
+ }
+ }
+
+ // remove this policy related entry in acl_policy_permission table
+ List policyPermMap = _policyPermissionDao.listByPolicy(policy.getId());
+ if (policyPermMap != null) {
+ for (IAMPolicyPermissionVO policyPerm : policyPermMap) {
+ _policyPermissionDao.remove(policyPerm.getId());
+ }
+ }
+
+ // remove this role from acl_role table
+ _aclPolicyDao.remove(iamPolicyId);
+ }
+ });
+
+ return true;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listIAMPolicies(long accountId) {
+
+ // static policies of the account
+ SearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder();
+ groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
+
+ GenericSearchBuilder policySB = _aclGroupPolicyMapDao.createSearchBuilder(Long.class);
+ policySB.selectFields(policySB.entity().getAclPolicyId());
+ policySB.join("accountgroupjoin", groupSB, groupSB.entity().getAclGroupId(), policySB.entity().getAclGroupId(),
+ JoinType.INNER);
+ policySB.done();
+ SearchCriteria policySc = policySB.create();
+ policySc.setJoinParameters("accountgroupjoin", "account", accountId);
+
+ List policyIds = _aclGroupPolicyMapDao.customSearch(policySc, null);
+ // add policies directly attached to the account
+ List acctPolicies = _aclAccountPolicyMapDao.listByAccountId(accountId);
+ for (IAMAccountPolicyMapVO p : acctPolicies) {
+ policyIds.add(p.getIamPolicyId());
+ }
+ if (policyIds.size() == 0) {
+ return new ArrayList();
+ }
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
+ @SuppressWarnings("rawtypes")
+ List policies = _aclPolicyDao.customSearch(sc, null);
+
+ return policies;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listIAMPoliciesByGroup(long groupId) {
+ List policyGrpMap = _aclGroupPolicyMapDao.listByGroupId(groupId);
+ if (policyGrpMap == null || policyGrpMap.size() == 0) {
+ return new ArrayList();
+ }
+
+ List policyIds = new ArrayList();
+ for (IAMGroupPolicyMapVO pg : policyGrpMap) {
+ policyIds.add(pg.getAclPolicyId());
+ }
+
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
+ @SuppressWarnings("rawtypes")
+ List policies = _aclPolicyDao.customSearch(sc, null);
+
+ return policies;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listRecursiveIAMPoliciesByGroup(long groupId) {
+ List policyGrpMap = _aclGroupPolicyMapDao.listByGroupId(groupId);
+ if (policyGrpMap == null || policyGrpMap.size() == 0) {
+ return new ArrayList();
+ }
+
+ List policyIds = new ArrayList();
+ for (IAMGroupPolicyMapVO pg : policyGrpMap) {
+ policyIds.add(pg.getAclPolicyId());
+ }
+
+ SearchBuilder permSb = _policyPermissionDao.createSearchBuilder();
+ permSb.and("isRecursive", permSb.entity().isRecursive(), Op.EQ);
+
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ sb.join("recursivePerm", permSb, sb.entity().getId(), permSb.entity().getAclPolicyId(),
+ JoinBuilder.JoinType.INNER);
+
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
+ sc.setJoinParameters("recursivePerm", "isRecursive", true);
+
+ @SuppressWarnings("rawtypes")
+ List policies = _aclPolicyDao.customSearch(sc, null);
+
+ return policies;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Pair, Integer> listIAMPolicies(Long iamPolicyId, String iamPolicyName, String path, Long startIndex, Long pageSize) {
+
+ if (iamPolicyId != null) {
+ IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy by id " + iamPolicyId);
+ }
+ }
+
+ Filter searchFilter = new Filter(IAMPolicyVO.class, "id", true, startIndex, pageSize);
+
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
+ sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
+ sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
+
+ SearchCriteria sc = sb.create();
+
+ if (iamPolicyName != null) {
+ sc.setParameters("name", iamPolicyName);
+ }
+
+ if (iamPolicyId != null) {
+ sc.setParameters("id", iamPolicyId);
+ }
+
+ sc.setParameters("path", path + "%");
+
+ Pair, Integer> policies = _aclPolicyDao.searchAndCount(sc, searchFilter);
+ @SuppressWarnings("rawtypes")
+ List policyList = policies.first();
+ return new Pair, Integer>(policyList, policies.second());
+ }
+
+ @DB
+ @Override
+ public IAMGroup attachIAMPoliciesToGroup(final List policyIds, final Long groupId) {
+ // get the Acl Group entity
+ IAMGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add roles to acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_policy_map table
+ for (Long policyId : policyIds) {
+ IAMPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+
+ IAMGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap == null) {
+ // not there already
+ grMap = new IAMGroupPolicyMapVO(groupId, policyId);
+ _aclGroupPolicyMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+
+ return group;
+ }
+
+ @DB
+ @Override
+ public IAMGroup removeIAMPoliciesFromGroup(final List policyIds, final Long groupId) {
+ // get the Acl Group entity
+ IAMGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove roles from acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_role_map table
+ for (Long policyId : policyIds) {
+ IAMPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+
+ IAMGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupPolicyMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+
+ @Override
+ public void attachIAMPolicyToAccounts(final Long policyId, final List acctIds) {
+ IAMPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policy to account.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_policy_map table
+ for (Long acctId : acctIds) {
+ IAMAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
+ if (acctMap == null) {
+ // not there already
+ acctMap = new IAMAccountPolicyMapVO(acctId, policyId);
+ _aclAccountPolicyMapDao.persist(acctMap);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void removeIAMPolicyFromAccounts(final Long policyId, final List acctIds) {
+ IAMPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policy to account.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_policy_map table
+ for (Long acctId : acctIds) {
+ IAMAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
+ if (acctMap != null) {
+ // exists
+ _aclAccountPolicyMapDao.remove(acctMap.getId());
+ }
+ }
+ }
+ });
+ }
+
+ @DB
+ @Override
+ public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
+ String action, String accessType, Permission perm, Boolean recursive) {
+ // get the Acl Policy entity
+ IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ + "; failed to add permission to policy.");
+ }
+
+ // add entry in acl_policy_permission table
+ IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, scopeId, action, perm);
+ if (permit == null) {
+ // not there already
+ permit = new IAMPolicyPermissionVO(iamPolicyId, action, entityType, accessType, scope, scopeId, perm,
+ recursive);
+ _policyPermissionDao.persist(permit);
+ }
+ return policy;
+
+ }
+
+ @DB
+ @Override
+ public IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
+ String action) {
+ // get the Acl Policy entity
+ IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ + "; failed to revoke permission from policy.");
+ }
+ // remove entry from acl_entity_permission table
+ IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, scopeId, action, Permission.Allow);
+ if (permit != null) {
+ // not removed yet
+ _policyPermissionDao.remove(permit.getId());
+ }
+ return policy;
+ }
+
+ @DB
+ @Override
+ public void removeIAMPermissionForEntity(final String entityType, final Long entityId) {
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entry from acl_entity_permission table
+ List permitList = _policyPermissionDao.listByEntity(entityType, entityId);
+ for (IAMPolicyPermissionVO permit : permitList) {
+ long policyId = permit.getAclPolicyId();
+ _policyPermissionDao.remove(permit.getId());
+
+ // remove the policy if there are no other permissions
+ if ((_policyPermissionDao.listByPolicy(policyId)).isEmpty()) {
+ deleteIAMPolicy(policyId);
+ }
+ }
+ }
+ });
+ }
+
+ @DB
+ @Override
+ public IAMPolicy resetIAMPolicy(long iamPolicyId) {
+ // get the Acl Policy entity
+ IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ + "; failed to reset the policy.");
+ }
+
+ SearchBuilder sb = _policyPermissionDao.createSearchBuilder();
+ sb.and("policyId", sb.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ sb.and("scope", sb.entity().getScope(), SearchCriteria.Op.EQ);
+ sb.done();
+ SearchCriteria permissionSC = sb.create();
+ permissionSC.setParameters("policyId", iamPolicyId);
+ _policyPermissionDao.expunge(permissionSC);
+
+ return policy;
+ }
+
+ @Override
+ public boolean isActionAllowedForPolicies(String action, List policies) {
+
+ boolean allowed = false;
+
+ if (policies == null || policies.size() == 0) {
+ return allowed;
+ }
+
+ List policyIds = new ArrayList();
+ for (IAMPolicy policy : policies) {
+ policyIds.add(policy.getId());
+ }
+
+ SearchBuilder sb = _policyPermissionDao.createSearchBuilder();
+ sb.and("action", sb.entity().getAction(), Op.EQ);
+ sb.and("policyId", sb.entity().getAclPolicyId(), Op.IN);
+
+ SearchCriteria sc = sb.create();
+ sc.setParameters("policyId", policyIds.toArray(new Object[policyIds.size()]));
+ sc.setParameters("action", action);
+
+ List permissions = _policyPermissionDao.customSearch(sc, null);
+
+ if (permissions != null && !permissions.isEmpty()) {
+ allowed = true;
+ }
+
+ return allowed;
+ }
+
+
+ @Override
+ public List getGrantedEntities(long accountId, String action, String scope) {
+ // Get the static Policies of the Caller
+ List policies = listIAMPolicies(accountId);
+ // for each policy, find granted permission within the given scope
+ List entityIds = new ArrayList();
+ for (IAMPolicy policy : policies) {
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action,
+ scope);
+ if (pp != null) {
+ for (IAMPolicyPermissionVO p : pp) {
+ if (p.getScopeId() != null) {
+ entityIds.add(p.getScopeId());
+ }
+ }
+ }
+ }
+ return entityIds;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List listPolicyPermissions(long policyId) {
+ @SuppressWarnings("rawtypes")
+ List pp = _policyPermissionDao.listByPolicy(policyId);
+ return pp;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listPolicyPermissionsByScope(long policyId, String action, String scope) {
+ @SuppressWarnings("rawtypes")
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policyId, action, scope);
+ return pp;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listPolicyPermissionByActionAndEntity(long policyId, String action,
+ String entityType) {
+ @SuppressWarnings("rawtypes")
+ List pp = _policyPermissionDao.listByPolicyActionAndEntity(policyId, action, entityType);
+ return pp;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List listPolicyPermissionByAccessAndEntity(long policyId, String accessType,
+ String entityType) {
+ @SuppressWarnings("rawtypes")
+ List pp = _policyPermissionDao.listByPolicyAccessAndEntity(policyId, accessType, entityType);
+ return pp;
+ }
+
+ @Override
+ public IAMPolicy getResourceOwnerPolicy() {
+ return _aclPolicyDao.findByName("RESOURCE_OWNER");
+ }
+
+ // search for policy with only one resource grant permission
+ @Override
+ public IAMPolicy getResourceGrantPolicy(String entityType, Long entityId, String accessType, String action) {
+ List policyList = _aclPolicyDao.listAll();
+ for (IAMPolicyVO policy : policyList){
+ List pp = listPolicyPermissions(policy.getId());
+ if ( pp != null && pp.size() == 1){
+ // resource grant policy should only have one ACL permission assigned
+ IAMPolicyPermission permit = pp.get(0);
+ if ( permit.getEntityType().equals(entityType) && permit.getScope().equals(PermissionScope.RESOURCE.toString()) && permit.getScopeId().longValue() == entityId.longValue()){
+ if (accessType != null && permit.getAccessType().equals(accessType)){
+ return policy;
+ } else if (action != null && permit.getAction().equals(action)) {
+ return policy;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDao.java
new file mode 100644
index 00000000000..4caf6590907
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDao.java
@@ -0,0 +1,17 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.IAMAccountPolicyMapVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMAccountPolicyMapDao extends GenericDao {
+
+ List listByAccountId(long acctId);
+
+ List listByPolicyId(long policyId);
+
+ IAMAccountPolicyMapVO findByAccountAndPolicy(long acctId, long policyId);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDaoImpl.java
new file mode 100644
index 00000000000..3ecca3bdb1a
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMAccountPolicyMapDaoImpl.java
@@ -0,0 +1,61 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.server.IAMAccountPolicyMapVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class IAMAccountPolicyMapDaoImpl extends GenericDaoBase implements IAMAccountPolicyMapDao {
+
+ private SearchBuilder ListByAccountId;
+ private SearchBuilder ListByPolicyId;
+ private SearchBuilder findByPolicyAccountId;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ ListByAccountId = createSearchBuilder();
+ ListByAccountId.and("accountId", ListByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+ ListByAccountId.done();
+
+ ListByPolicyId = createSearchBuilder();
+ ListByPolicyId.and("policyId", ListByPolicyId.entity().getIamPolicyId(), SearchCriteria.Op.EQ);
+ ListByPolicyId.done();
+
+ findByPolicyAccountId = createSearchBuilder();
+ findByPolicyAccountId.and("policyId", findByPolicyAccountId.entity().getIamPolicyId(), SearchCriteria.Op.EQ);
+ findByPolicyAccountId.and("accountId", findByPolicyAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+ findByPolicyAccountId.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByAccountId(long acctId) {
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", acctId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyId(long policyId) {
+ SearchCriteria sc = ListByPolicyId.create();
+ sc.setParameters("policyId", policyId);
+ return listBy(sc);
+ }
+
+ @Override
+ public IAMAccountPolicyMapVO findByAccountAndPolicy(long acctId, long policyId) {
+ SearchCriteria sc = findByPolicyAccountId.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("accountId", acctId);
+ return findOneBy(sc);
+ }
+}
\ No newline at end of file
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDao.java
new file mode 100644
index 00000000000..a94dbaae9c7
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDao.java
@@ -0,0 +1,40 @@
+// 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.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.IAMGroupAccountMapVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMGroupAccountMapDao extends GenericDao {
+
+ List listByGroupId(long groupId);
+
+ List listByAccountId(long accountId);
+
+ IAMGroupAccountMapVO findAccountInAdminGroup(long accountId);
+
+ IAMGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId);
+
+ void removeAccountFromGroups(long accountId);
+
+ IAMGroupAccountMapVO findAccountInDomainAdminGroup(long accountId);
+
+ IAMGroupAccountMapVO findAccountInUserGroup(long accountId);
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDaoImpl.java
new file mode 100644
index 00000000000..4bb5d1a59fb
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupAccountMapDaoImpl.java
@@ -0,0 +1,119 @@
+// 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.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.server.IAMGroupAccountMapVO;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class IAMGroupAccountMapDaoImpl extends GenericDaoBase implements IAMGroupAccountMapDao {
+ private SearchBuilder ListByGroupId;
+ private SearchBuilder ListByAccountId;
+ private SearchBuilder _findByAccountAndGroupId;
+
+ public static final Logger s_logger = Logger.getLogger(IAMGroupAccountMapDaoImpl.class.getName());
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ ListByGroupId = createSearchBuilder();
+ ListByGroupId.and("groupId", ListByGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ ListByGroupId.done();
+
+ ListByAccountId = createSearchBuilder();
+ ListByAccountId.and("accountId", ListByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+ ListByAccountId.done();
+
+ _findByAccountAndGroupId = createSearchBuilder();
+ _findByAccountAndGroupId
+ .and("groupId", _findByAccountAndGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ _findByAccountAndGroupId.and("accountId", _findByAccountAndGroupId.entity().getAccountId(),
+ SearchCriteria.Op.EQ);
+ _findByAccountAndGroupId.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByGroupId(long groupId) {
+ SearchCriteria sc = ListByGroupId.create();
+ sc.setParameters("groupId", groupId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByAccountId(long accountId) {
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", accountId);
+ return listBy(sc);
+ }
+
+ @Override
+ public IAMGroupAccountMapVO findAccountInAdminGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 2);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public IAMGroupAccountMapVO findAccountInDomainAdminGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 3);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public IAMGroupAccountMapVO findAccountInUserGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 1);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public IAMGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", acctId);
+ sc.setParameters("groupId", groupId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public void removeAccountFromGroups(long accountId) {
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", accountId);
+
+ int rowsRemoved = remove(sc);
+ if (rowsRemoved > 0) {
+ s_logger.debug("Removed account id=" + accountId + " from " + rowsRemoved + " groups");
+ }
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDao.java
new file mode 100644
index 00000000000..54408a6d390
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDao.java
@@ -0,0 +1,28 @@
+// 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.server.dao;
+
+import org.apache.cloudstack.iam.api.IAMGroup;
+import org.apache.cloudstack.iam.server.IAMGroupVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMGroupDao extends GenericDao {
+
+ IAMGroup findByName(String path, String groupName);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDaoImpl.java
new file mode 100644
index 00000000000..45be0b3f21c
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupDaoImpl.java
@@ -0,0 +1,59 @@
+// 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.server.dao;
+
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.IAMGroup;
+import org.apache.cloudstack.iam.server.IAMGroupVO;
+import org.springframework.stereotype.Component;
+
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class IAMGroupDaoImpl extends GenericDaoBase implements IAMGroupDao {
+ private SearchBuilder nameSearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ nameSearch = createSearchBuilder();
+ nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
+ nameSearch.and("path", nameSearch.entity().getPath(), SearchCriteria.Op.EQ);
+ nameSearch.done();
+
+
+ return true;
+ }
+
+ @Override
+ public IAMGroup findByName(String path, String name) {
+ SearchCriteria sc = nameSearch.create();
+ sc.setParameters("name", name);
+ if (path != null) {
+ sc.setParameters("path", path);
+ }
+ return findOneBy(sc);
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDao.java
new file mode 100644
index 00000000000..6a2df89ab75
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDao.java
@@ -0,0 +1,16 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.IAMGroupPolicyMapVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMGroupPolicyMapDao extends GenericDao {
+
+ List listByGroupId(long groupId);
+
+ List listByPolicyId(long policyId);
+
+ IAMGroupPolicyMapVO findByGroupAndPolicy(long groupId, long policyId);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDaoImpl.java
new file mode 100644
index 00000000000..95b6bac3712
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMGroupPolicyMapDaoImpl.java
@@ -0,0 +1,61 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.server.IAMGroupPolicyMapVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class IAMGroupPolicyMapDaoImpl extends GenericDaoBase implements IAMGroupPolicyMapDao {
+
+ private SearchBuilder ListByGroupId;
+ private SearchBuilder ListByPolicyId;
+ private SearchBuilder findByPolicyGroupId;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ ListByGroupId = createSearchBuilder();
+ ListByGroupId.and("groupId", ListByGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ ListByGroupId.done();
+
+ ListByPolicyId = createSearchBuilder();
+ ListByPolicyId.and("policyId", ListByPolicyId.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ ListByPolicyId.done();
+
+ findByPolicyGroupId = createSearchBuilder();
+ findByPolicyGroupId.and("policyId", findByPolicyGroupId.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ findByPolicyGroupId.and("groupId", findByPolicyGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ findByPolicyGroupId.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByGroupId(long groupId) {
+ SearchCriteria sc = ListByGroupId.create();
+ sc.setParameters("groupId", groupId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyId(long policyId) {
+ SearchCriteria sc = ListByPolicyId.create();
+ sc.setParameters("policyId", policyId);
+ return listBy(sc);
+ }
+
+ @Override
+ public IAMGroupPolicyMapVO findByGroupAndPolicy(long groupId, long policyId) {
+ SearchCriteria sc = findByPolicyGroupId.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("groupId", groupId);
+ return findOneBy(sc);
+ }
+}
\ No newline at end of file
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDao.java
new file mode 100644
index 00000000000..ace7d8585ac
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDao.java
@@ -0,0 +1,28 @@
+// 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.server.dao;
+
+import org.apache.cloudstack.iam.api.IAMPolicy;
+import org.apache.cloudstack.iam.server.IAMPolicyVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMPolicyDao extends GenericDao {
+
+ IAMPolicy findByName(String policyName);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDaoImpl.java
new file mode 100644
index 00000000000..293cf6f59ee
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyDaoImpl.java
@@ -0,0 +1,57 @@
+// 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.server.dao;
+
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.IAMPolicy;
+import org.apache.cloudstack.iam.server.IAMPolicyVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class IAMPolicyDaoImpl extends GenericDaoBase implements IAMPolicyDao {
+ private SearchBuilder nameSearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ nameSearch = createSearchBuilder();
+ nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
+ // nameSearch.and("domainId", nameSearch.entity().getDomainId(),
+ // SearchCriteria.Op.EQ);
+ nameSearch.done();
+
+
+ return true;
+ }
+
+ @Override
+ public IAMPolicy findByName(String name) {
+ SearchCriteria sc = nameSearch.create();
+ sc.setParameters("name", name);
+
+ return findOneBy(sc);
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java
new file mode 100644
index 00000000000..cdcb02b1dee
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java
@@ -0,0 +1,39 @@
+// 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.server.dao;
+import java.util.List;
+
+import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
+import org.apache.cloudstack.iam.server.IAMPolicyPermissionVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface IAMPolicyPermissionDao extends GenericDao {
+
+ List listByPolicy(long policyId);
+
+ IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId,
+ String action, Permission perm);
+
+ List listGrantedByActionAndScope(long policyId, String action, String scope);
+
+ List listByPolicyActionAndEntity(long policyId, String action, String entityType);
+
+ List listByPolicyAccessAndEntity(long policyId, String accessType, String entityType);
+
+ List listByEntity(String entityType, Long entityId);
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java
new file mode 100644
index 00000000000..3f976cfefce
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java
@@ -0,0 +1,129 @@
+// 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.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
+import org.apache.cloudstack.iam.server.IAMPolicyPermissionVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class IAMPolicyPermissionDaoImpl extends GenericDaoBase implements
+ IAMPolicyPermissionDao {
+
+ private SearchBuilder policyIdSearch;
+ private SearchBuilder fullSearch;
+ private SearchBuilder actionScopeSearch;
+ private SearchBuilder entitySearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ policyIdSearch = createSearchBuilder();
+ policyIdSearch.and("policyId", policyIdSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ policyIdSearch.done();
+
+ fullSearch = createSearchBuilder();
+ fullSearch.and("policyId", fullSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ fullSearch.and("entityType", fullSearch.entity().getEntityType(), SearchCriteria.Op.EQ);
+ fullSearch.and("scope", fullSearch.entity().getScope(), SearchCriteria.Op.EQ);
+ fullSearch.and("scopeId", fullSearch.entity().getScopeId(), SearchCriteria.Op.EQ);
+ fullSearch.and("action", fullSearch.entity().getAction(), SearchCriteria.Op.EQ);
+ fullSearch.and("permission", fullSearch.entity().getPermission(), SearchCriteria.Op.EQ);
+ fullSearch.and("accessType", fullSearch.entity().getAccessType(), SearchCriteria.Op.EQ);
+ fullSearch.done();
+
+ actionScopeSearch = createSearchBuilder();
+ actionScopeSearch.and("policyId", actionScopeSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("scope", actionScopeSearch.entity().getScope(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("action", actionScopeSearch.entity().getAction(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("permission", actionScopeSearch.entity().getPermission(), SearchCriteria.Op.EQ);
+ actionScopeSearch.done();
+
+ entitySearch = createSearchBuilder();
+ entitySearch.and("entityType", entitySearch.entity().getEntityType(), SearchCriteria.Op.EQ);
+ entitySearch.and("scopeId", entitySearch.entity().getScopeId(), SearchCriteria.Op.EQ);
+ entitySearch.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByPolicy(long policyId) {
+ SearchCriteria sc = policyIdSearch.create();
+ sc.setParameters("policyId", policyId);
+ return listBy(sc);
+ }
+
+ @Override
+ public IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId,
+ String action, Permission perm) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("scope", scope);
+ sc.setParameters("scopeId", scopeId);
+ sc.setParameters("action", action);
+ sc.setParameters("permission", perm);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public List listGrantedByActionAndScope(long policyId, String action, String scope) {
+ SearchCriteria sc = actionScopeSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("action", action);
+ sc.setParameters("scope", scope);
+ sc.setParameters("permission", Permission.Allow);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyActionAndEntity(long policyId, String action, String entityType) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("action", action);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyAccessAndEntity(long policyId, String accessType,
+ String entityType) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("accessType", accessType);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByEntity(String entityType, Long entityId) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("scopeId", entityId);
+ return listBy(sc);
+ }
+
+}
diff --git a/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java b/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
new file mode 100644
index 00000000000..53cfc71f936
--- /dev/null
+++ b/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
@@ -0,0 +1,211 @@
+// 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 static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+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.iam.api.IAMGroup;
+import org.apache.cloudstack.iam.api.IAMPolicy;
+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.iam.server.IAMServiceImpl;
+import org.apache.cloudstack.iam.server.dao.IAMAccountPolicyMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupAccountMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupDao;
+import org.apache.cloudstack.iam.server.dao.IAMGroupPolicyMapDao;
+import org.apache.cloudstack.iam.server.dao.IAMPolicyDao;
+import org.apache.cloudstack.iam.server.dao.IAMPolicyPermissionDao;
+import org.apache.cloudstack.test.utils.SpringUtils;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.db.SearchCriteria;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
+public class IAMServiceUnitTest {
+
+ @Inject
+ IAMService _iamService;
+
+ @Inject
+ IAMPolicyDao _aclPolicyDao;
+
+ @Inject
+ IAMGroupDao _aclGroupDao;
+
+ @Inject
+ EntityManager _entityMgr;
+
+ @Inject
+ IAMGroupPolicyMapDao _aclGroupPolicyMapDao;
+
+ @Inject
+ IAMGroupAccountMapDao _aclGroupAccountMapDao;
+
+ @Inject
+ IAMPolicyPermissionDao _policyPermissionDao;
+
+ @BeforeClass
+ public static void setUpClass() throws ConfigurationException {
+ }
+
+ @Before
+ public void setUp() {
+ ComponentContext.initComponentsLifeCycle();
+ IAMGroupVO group = new IAMGroupVO("group1", "my first group");
+ Mockito.when(_aclGroupDao.persist(Mockito.any(IAMGroupVO.class))).thenReturn(group);
+ List groups = new ArrayList();
+ groups.add(group);
+ when(_aclGroupDao.search(Mockito.any(SearchCriteria.class), Mockito.any(com.cloud.utils.db.Filter.class)))
+ .thenReturn(groups);
+
+ IAMPolicyVO policy = new IAMPolicyVO("policy1", "my first policy");
+ Mockito.when(_aclPolicyDao.persist(Mockito.any(IAMPolicyVO.class))).thenReturn(policy);
+
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void createAclGroupTest() {
+ IAMGroup group = _iamService.createIAMGroup("group1", "my first group", "/root/mydomain");
+ assertNotNull("Acl group 'group1' failed to create ", group);
+
+ IAMGroupVO group2 = new IAMGroupVO("group1", "my second group");
+ when(_aclGroupDao.findByName(eq("/root/mydomain"), eq("group1"))).thenReturn(group2);
+
+ IAMGroup group3 = _iamService.createIAMGroup("group1", "my first group", "/root/mydomain");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void deleteAclGroupInvalidIdTest() {
+ when(_aclGroupDao.findById(20L)).thenReturn(null);
+ _iamService.deleteIAMGroup(20L);
+ }
+
+ @Test
+ public void accountGroupMaptest() {
+ // create group
+ IAMGroupVO group = new IAMGroupVO("group1", "my first group");
+
+ // add account to group
+ List accountIds = new ArrayList();
+ accountIds.add(100L);
+ when(_aclGroupDao.findById(20L)).thenReturn(group);
+ _iamService.addAccountsToGroup(accountIds, 20L);
+
+ _iamService.removeAccountsFromGroup(accountIds, 20L);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void createAclPolicyTest() {
+ IAMPolicy policy = _iamService.createIAMPolicy("policy1", "my first policy", null, "/root/mydomain");
+ assertNotNull("Acl policy 'policy1' failed to create ", policy);
+
+ IAMPolicyVO rvo = new IAMPolicyVO("policy2", "second policy");
+ when(_aclPolicyDao.findByName(eq("policy2"))).thenReturn(rvo);
+
+ _iamService.createIAMPolicy("policy2", "second policy", null, "/root/mydomain");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void deleteAclPolicyInvalidIdTest() {
+ when(_aclPolicyDao.findById(34L)).thenReturn(null);
+ _iamService.deleteIAMPolicy(34L);
+ }
+
+ @Configuration
+ @ComponentScan(basePackageClasses = {IAMServiceImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false)
+ public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
+
+ @Bean
+ public IAMPolicyDao aclPolicyDao() {
+ return Mockito.mock(IAMPolicyDao.class);
+ }
+
+ @Bean
+ public IAMGroupDao aclGroupDao() {
+ return Mockito.mock(IAMGroupDao.class);
+ }
+
+ @Bean
+ public EntityManager entityManager() {
+ return Mockito.mock(EntityManager.class);
+ }
+
+ @Bean
+ public IAMGroupPolicyMapDao aclGroupPolicyMapDao() {
+ return Mockito.mock(IAMGroupPolicyMapDao.class);
+ }
+
+ @Bean
+ public IAMGroupAccountMapDao aclGroupAccountMapDao() {
+ return Mockito.mock(IAMGroupAccountMapDao.class);
+ }
+
+ @Bean
+ public IAMAccountPolicyMapDao aclAccountPolicyMapDao() {
+ return Mockito.mock(IAMAccountPolicyMapDao.class);
+ }
+
+ @Bean
+ public IAMPolicyPermissionDao aclPolicyPermissionDao() {
+ return Mockito.mock(IAMPolicyPermissionDao.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);
+ }
+ }
+ }
+}
diff --git a/services/iam/server/test/resources/db.properties b/services/iam/server/test/resources/db.properties
new file mode 100644
index 00000000000..e1b5fe9a2c1
--- /dev/null
+++ b/services/iam/server/test/resources/db.properties
@@ -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