You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2014/01/28 19:00:40 UTC

git commit: updated refs/heads/rbac to 748dc15

Updated Branches:
  refs/heads/rbac 91317dc49 -> 748dc1541


Support attaching policy to account.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/748dc154
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/748dc154
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/748dc154

Branch: refs/heads/rbac
Commit: 748dc1541cabc7b444102843e3f23b593e4ab9a2
Parents: 91317dc
Author: Min Chen <mi...@citrix.com>
Authored: Tue Jan 28 09:58:50 2014 -0800
Committer: Min Chen <mi...@citrix.com>
Committed: Tue Jan 28 10:00:17 2014 -0800

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |   1 +
 client/tomcatconf/commands.properties.in        |   2 +
 .../cloudstack/acl/api/AclApiService.java       |   8 +-
 .../cloudstack/acl/api/AclApiServiceImpl.java   |  18 +++
 .../command/AttachAclPolicyToAccountCmd.java    | 122 +++++++++++++++++++
 .../command/RemoveAclPolicyFromAccountCmd.java  | 122 +++++++++++++++++++
 .../core/spring-iam-server-context.xml          |   2 +
 .../apache/cloudstack/iam/api/IAMService.java   |   4 +
 .../iam/server/AclAccountPolicyMapVO.java       |  77 ++++++++++++
 .../cloudstack/iam/server/IAMServiceImpl.java   |  76 ++++++------
 .../iam/server/dao/AclAccountPolicyMapDao.java  |  17 +++
 .../server/dao/AclAccountPolicyMapDaoImpl.java  |  61 ++++++++++
 .../cloudstack/iam/IAMServiceUnitTest.java      |   6 +
 setup/db/db/schema-430to440.sql                 |  19 ++-
 14 files changed, 489 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index fa4d342..ef433f7 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -459,6 +459,7 @@ public class EventTypes {
     public static final String EVENT_ACL_GROUP_DELETE = "ACLGROUP.DELETE";
     public static final String EVENT_ACL_GROUP_GRANT = "ACLGROUP.GRANT";
     public static final String EVENT_ACL_GROUP_REVOKE = "ACLGROUP.REVOKE";
+    public static final String EVENT_ACL_ACCOUNT_POLICY_UPDATE = "ACLACCOUNTPOLICY.UPDATE";
 
     // Object store migration
     public static final String EVENT_MIGRATE_PREPARE_SECONDARY_STORAGE = "MIGRATE.PREPARE.SS";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index e68b53a..29dfdad 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -718,6 +718,8 @@ addAccountToAclGroup=1
 removeAccountFromAclGroup=1
 attachAclPolicyToAclGroup=1
 removeAclPolicyFromAclGroup=1
+attachAclPolicyToAccount=1
+removeAclPolicyFromAccount=1
 
 #### juniper-contrail commands
 createServiceInstance=1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java
----------------------------------------------------------------------
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java
index 98abd13..eb08de5 100644
--- a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java
@@ -50,9 +50,13 @@ public interface AclApiService extends PluggableService {
 
     List<AclPolicy> listAclPolicies(long accountId);
 
-    AclGroup attachAclPoliciesToGroup(List<Long> roleIds, Long groupId);
+    AclGroup attachAclPoliciesToGroup(List<Long> policyIds, Long groupId);
 
-    AclGroup removeAclPoliciesFromGroup(List<Long> roleIds, Long groupId);
+    AclGroup removeAclPoliciesFromGroup(List<Long> policyIds, Long groupId);
+
+    void attachAclPolicyToAccounts(Long policyId, List<Long> accountIds);
+
+    void removeAclPolicyFromAccounts(Long policyId, List<Long> accountIds);
 
     AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java
index 12e3748..d50f4f2 100644
--- a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java
@@ -32,6 +32,7 @@ import org.apache.cloudstack.acl.PermissionScope;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.acl.api.command.AddAccountToAclGroupCmd;
 import org.apache.cloudstack.acl.api.command.AddAclPermissionToAclPolicyCmd;
+import org.apache.cloudstack.acl.api.command.AttachAclPolicyToAccountCmd;
 import org.apache.cloudstack.acl.api.command.AttachAclPolicyToAclGroupCmd;
 import org.apache.cloudstack.acl.api.command.CreateAclGroupCmd;
 import org.apache.cloudstack.acl.api.command.CreateAclPolicyCmd;
@@ -41,6 +42,7 @@ import org.apache.cloudstack.acl.api.command.ListAclGroupsCmd;
 import org.apache.cloudstack.acl.api.command.ListAclPoliciesCmd;
 import org.apache.cloudstack.acl.api.command.RemoveAccountFromAclGroupCmd;
 import org.apache.cloudstack.acl.api.command.RemoveAclPermissionFromAclPolicyCmd;
+import org.apache.cloudstack.acl.api.command.RemoveAclPolicyFromAccountCmd;
 import org.apache.cloudstack.acl.api.command.RemoveAclPolicyFromAclGroupCmd;
 import org.apache.cloudstack.acl.api.response.AclGroupResponse;
 import org.apache.cloudstack.acl.api.response.AclPermissionResponse;
@@ -245,6 +247,20 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man
 
     @DB
     @Override
+    @ActionEvent(eventType = EventTypes.EVENT_ACL_ACCOUNT_POLICY_UPDATE, eventDescription = "Attaching policy to accounts")
+    public void attachAclPolicyToAccounts(final Long policyId, final List<Long> accountIds) {
+        _iamSrv.attachAclPolicyToAccounts(policyId, accountIds);
+    }
+
+    @DB
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_ACL_ACCOUNT_POLICY_UPDATE, eventDescription = "Removing policy from accounts")
+    public void removeAclPolicyFromAccounts(final Long policyId, final List<Long> accountIds) {
+        _iamSrv.removeAclPolicyFromAccounts(policyId, accountIds);
+    }
+
+    @DB
+    @Override
     @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting acl permission to Acl Policy")
     public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm) {
         Class<?> cmdClass = _apiServer.getCmdClass(action);
@@ -439,6 +455,8 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man
         cmdList.add(ListAclGroupsCmd.class);
         cmdList.add(AddAccountToAclGroupCmd.class);
         cmdList.add(RemoveAccountFromAclGroupCmd.class);
+        cmdList.add(AttachAclPolicyToAccountCmd.class);
+        cmdList.add(RemoveAclPolicyFromAccountCmd.class);
         return cmdList;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AttachAclPolicyToAccountCmd.java
----------------------------------------------------------------------
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AttachAclPolicyToAccountCmd.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AttachAclPolicyToAccountCmd.java
new file mode 100644
index 0000000..b88df2b
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AttachAclPolicyToAccountCmd.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.acl.api.command;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.api.AclApiService;
+import org.apache.cloudstack.acl.api.response.AclPolicyResponse;
+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.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "attachAclPolicyToAccount", description = "attach acl policy to accounts", responseObject = SuccessResponse.class)
+public class AttachAclPolicyToAccountCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AttachAclPolicyToAccountCmd.class.getName());
+    private static final String s_name = "attachaclpolicytoaccountresponse";
+
+    @Inject
+    public AclApiService _aclApiSrv;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+
+    @ACL
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclPolicyResponse.class,
+            required = true, description = "The ID of the acl 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("Acl policy Id: " + getId());
+        _aclApiSrv.attachAclPolicyToAccounts(id, accountIdList);
+        SuccessResponse response = new SuccessResponse();
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_ACCOUNT_POLICY_UPDATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "adding acl policy to accounts";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.Account;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/RemoveAclPolicyFromAccountCmd.java
----------------------------------------------------------------------
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/RemoveAclPolicyFromAccountCmd.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/RemoveAclPolicyFromAccountCmd.java
new file mode 100644
index 0000000..74b3092
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/RemoveAclPolicyFromAccountCmd.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.acl.api.command;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.api.AclApiService;
+import org.apache.cloudstack.acl.api.response.AclGroupResponse;
+import org.apache.cloudstack.acl.api.response.AclPolicyResponse;
+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.SuccessResponse;
+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 = "removeAclPolicyFromAccount", description = "remove acl policy from accounts", responseObject = SuccessResponse.class)
+public class RemoveAclPolicyFromAccountCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(RemoveAclPolicyFromAccountCmd.class.getName());
+    private static final String s_name = "removeaclpolicyfromaccountresponse";
+
+    @Inject
+    public AclApiService _aclApiSrv;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+
+    @ACL
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+            required = true, description = "The ID of the acl group")
+    private Long id;
+
+    @ACL
+    @Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AclPolicyResponse.class, description = "comma separated list of acl policy id that are going to be applied to the acl 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("Acl policy Id: " + getId());
+        _aclApiSrv.removeAclPolicyFromAccounts(id, accountIdList);
+        SuccessResponse response = new SuccessResponse();
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_ACCOUNT_POLICY_UPDATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "removing acl policy from accounts";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.Account;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml
----------------------------------------------------------------------
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
index 16dfd4a..82faa70 100644
--- 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
@@ -32,6 +32,8 @@
     <bean id="AclGroupAccountMapDaoImpl" class="org.apache.cloudstack.iam.server.dao.AclGroupAccountMapDaoImpl" />
     <bean id="AclGroupPolicyMapDaoImpl" class="org.apache.cloudstack.iam.server.dao.AclGroupPolicyMapDaoImpl" />    
     <bean id="AclPolicyPermissionDaoImpl" class="org.apache.cloudstack.iam.server.dao.AclPolicyPermissionDaoImpl" />
+    <bean id="AclAccountPolicyMapDaoImpl" class="org.apache.cloudstack.iam.server.dao.AclAccountPolicyMapDaoImpl" />    
+
         
     <bean id="IAMServiceImpl" class="org.apache.cloudstack.iam.server.IAMServiceImpl" />
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
----------------------------------------------------------------------
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
index 90dbb57..aad982b 100644
--- a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
@@ -54,6 +54,10 @@ public interface IAMService {
 
     AclGroup removeAclPoliciesFromGroup(List<Long> policyIds, Long groupId);
 
+    void attachAclPolicyToAccounts(Long policyId, List<Long> acctIds);
+
+    void removeAclPolicyFromAccounts(Long policyId, List<Long> acctIds);
+
     AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId,
             String action, String accessType, Permission perm);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/src/org/apache/cloudstack/iam/server/AclAccountPolicyMapVO.java
----------------------------------------------------------------------
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclAccountPolicyMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclAccountPolicyMapVO.java
new file mode 100644
index 0000000..b491e6e
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclAccountPolicyMapVO.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 = ("acl_account_policy_map"))
+public class AclAccountPolicyMapVO {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "account_id")
+    private long accountId;
+
+    @Column(name = "policy_id")
+    private long aclPolicyId;
+
+    @Column(name = GenericDao.REMOVED_COLUMN)
+    private Date removed;
+
+    @Column(name = GenericDao.CREATED_COLUMN)
+    private Date created;
+
+    public AclAccountPolicyMapVO() {
+    }
+
+    public AclAccountPolicyMapVO(long accountId, long aclPolicyId) {
+        this.accountId = accountId;
+        this.aclPolicyId = aclPolicyId;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public long getAccountId() {
+        return accountId;
+    }
+
+    public long getAclPolicyId() {
+        return aclPolicyId;
+    }
+
+    public Date getRemoved() {
+        return removed;
+    }
+
+    public Date getCreated() {
+        return created;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
----------------------------------------------------------------------
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
index d84dad4..0745e62 100644
--- a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
@@ -29,6 +29,7 @@ import org.apache.cloudstack.iam.api.AclPolicy;
 import org.apache.cloudstack.iam.api.AclPolicyPermission;
 import org.apache.cloudstack.iam.api.AclPolicyPermission.Permission;
 import org.apache.cloudstack.iam.api.IAMService;
+import org.apache.cloudstack.iam.server.dao.AclAccountPolicyMapDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupAccountMapDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupPolicyMapDao;
@@ -71,6 +72,9 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
     AclGroupPolicyMapDao _aclGroupPolicyMapDao;
 
     @Inject
+    AclAccountPolicyMapDao _aclAccountPolicyMapDao;
+
+    @Inject
     AclGroupAccountMapDao _aclGroupAccountMapDao;
 
     @Inject
@@ -341,7 +345,12 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
         policySc.setJoinParameters("accountgroupjoin", "account", accountId);
 
         List<Long> policyIds = _aclGroupPolicyMapDao.customSearch(policySc, null);
-        if (policyIds == null || policyIds.size() == 0) {
+        // add policies directly attached to the account
+        List<AclAccountPolicyMapVO> acctPolicies = _aclAccountPolicyMapDao.listByAccountId(accountId);
+        for (AclAccountPolicyMapVO p : acctPolicies) {
+            policyIds.add(p.getAclPolicyId());
+        }
+        if (policyIds.size() == 0) {
             return new ArrayList<AclPolicy>();
         }
         SearchBuilder<AclPolicyVO> sb = _aclPolicyDao.createSearchBuilder();
@@ -350,6 +359,7 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
         sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
         @SuppressWarnings("rawtypes")
         List policies = _aclPolicyDao.customSearch(sc, null);
+
         return policies;
 
     }
@@ -479,70 +489,54 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
         return group;
     }
 
-    /*
-    @DB
+
     @Override
-    @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting permission to Acl Role")
-    public AclP addAclPermissionToAclPolicy(final long aclRoleId, final List<String> apiNames) {
-        Account caller = CallContext.current().getCallingAccount();
-        // get the Acl Role entity
-        AclRole role = _aclPolicyDao.findById(aclRoleId);
-        if (role == null) {
-            throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
-                    + "; failed to grant permission to role.");
+    public void attachAclPolicyToAccounts(final Long policyId, final List<Long> acctIds) {
+        AclPolicy policy = _aclPolicyDao.findById(policyId);
+        if (policy == null) {
+            throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+                    + "; failed to add policy to account.");
         }
-        // check permissions
-        _accountMgr.checkAccess(caller, null, true, role);
 
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override
             public void doInTransactionWithoutResult(TransactionStatus status) {
-                // add entries in acl_api_permission table
-                for (String api : apiNames) {
-                    AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
-                    if (perm == null) {
+                // add entries in acl_group_policy_map table
+                for (Long acctId : acctIds) {
+                    AclAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
+                    if (acctMap == null) {
                         // not there already
-                        perm = new AclApiPermissionVO(aclRoleId, api);
-                        _apiPermissionDao.persist(perm);
+                        acctMap = new AclAccountPolicyMapVO(acctId, policyId);
+                        _aclAccountPolicyMapDao.persist(acctMap);
                     }
                 }
             }
         });
-
-        return role;
-
     }
 
-    @DB
     @Override
-    @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_REVOKE, eventDescription = "Revoking permission from Acl Role")
-    public AclRole revokeApiPermissionFromAclRole(final long aclRoleId, final List<String> apiNames) {
-        Account caller = CallContext.current().getCallingAccount();
-        // get the Acl Role entity
-        AclRole role = _aclPolicyDao.findById(aclRoleId);
-        if (role == null) {
-            throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
-                    + "; failed to revoke permission from role.");
+    public void removeAclPolicyFromAccounts(final Long policyId, final List<Long> acctIds) {
+        AclPolicy policy = _aclPolicyDao.findById(policyId);
+        if (policy == null) {
+            throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+                    + "; failed to add policy to account.");
         }
-        // check permissions
-        _accountMgr.checkAccess(caller, null, true, role);
 
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override
             public void doInTransactionWithoutResult(TransactionStatus status) {
-                // remove entries from acl_api_permission table
-                for (String api : apiNames) {
-                    AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
-                    if (perm != null) {
-                        // not removed yet
-                        _apiPermissionDao.remove(perm.getId());
+                // add entries in acl_group_policy_map table
+                for (Long acctId : acctIds) {
+                    AclAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
+                    if (acctMap == null) {
+                        // not there already
+                        acctMap = new AclAccountPolicyMapVO(acctId, policyId);
+                        _aclAccountPolicyMapDao.remove(acctMap.getId());
                     }
                 }
             }
         });
-        return role;
     }
-    */
 
     @DB
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDao.java
----------------------------------------------------------------------
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDao.java
new file mode 100644
index 0000000..83b8147
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDao.java
@@ -0,0 +1,17 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.AclAccountPolicyMapVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface AclAccountPolicyMapDao extends GenericDao<AclAccountPolicyMapVO, Long> {
+
+    List<AclAccountPolicyMapVO> listByAccountId(long acctId);
+
+    List<AclAccountPolicyMapVO> listByPolicyId(long policyId);
+
+    AclAccountPolicyMapVO findByAccountAndPolicy(long acctId, long policyId);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDaoImpl.java
----------------------------------------------------------------------
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDaoImpl.java
new file mode 100644
index 0000000..51091a6
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclAccountPolicyMapDaoImpl.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.AclAccountPolicyMapVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class AclAccountPolicyMapDaoImpl extends GenericDaoBase<AclAccountPolicyMapVO, Long> implements AclAccountPolicyMapDao {
+
+    private SearchBuilder<AclAccountPolicyMapVO> ListByAccountId;
+    private SearchBuilder<AclAccountPolicyMapVO> ListByPolicyId;
+    private SearchBuilder<AclAccountPolicyMapVO> findByPolicyAccountId;
+
+    @Override
+    public boolean configure(String name, Map<String, Object> 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().getAclPolicyId(), SearchCriteria.Op.EQ);
+        ListByPolicyId.done();
+
+        findByPolicyAccountId = createSearchBuilder();
+        findByPolicyAccountId.and("policyId", findByPolicyAccountId.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+        findByPolicyAccountId.and("accountId", findByPolicyAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+        findByPolicyAccountId.done();
+
+        return true;
+    }
+
+    @Override
+    public List<AclAccountPolicyMapVO> listByAccountId(long acctId) {
+        SearchCriteria<AclAccountPolicyMapVO> sc = ListByAccountId.create();
+        sc.setParameters("accountId", acctId);
+        return listBy(sc);
+    }
+
+    @Override
+    public List<AclAccountPolicyMapVO> listByPolicyId(long policyId) {
+        SearchCriteria<AclAccountPolicyMapVO> sc = ListByPolicyId.create();
+        sc.setParameters("policyId", policyId);
+        return listBy(sc);
+    }
+
+    @Override
+    public AclAccountPolicyMapVO findByAccountAndPolicy(long acctId, long policyId) {
+        SearchCriteria<AclAccountPolicyMapVO> sc = findByPolicyAccountId.create();
+        sc.setParameters("policyId", policyId);
+        sc.setParameters("accountId", acctId);
+        return findOneBy(sc);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
----------------------------------------------------------------------
diff --git a/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java b/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
index 5b1e57b..03973e2 100644
--- a/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
+++ b/services/iam/server/test/org/apache/cloudstack/iam/IAMServiceUnitTest.java
@@ -51,6 +51,7 @@ import org.apache.cloudstack.iam.api.IAMService;
 import org.apache.cloudstack.iam.server.AclGroupVO;
 import org.apache.cloudstack.iam.server.AclPolicyVO;
 import org.apache.cloudstack.iam.server.IAMServiceImpl;
+import org.apache.cloudstack.iam.server.dao.AclAccountPolicyMapDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupAccountMapDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupDao;
 import org.apache.cloudstack.iam.server.dao.AclGroupPolicyMapDao;
@@ -189,6 +190,11 @@ public class IAMServiceUnitTest {
         }
 
         @Bean
+        public AclAccountPolicyMapDao aclAccountPolicyMapDao() {
+            return Mockito.mock(AclAccountPolicyMapDao.class);
+        }
+
+        @Bean
         public AclPolicyPermissionDao aclPolicyPermissionDao() {
             return Mockito.mock(AclPolicyPermissionDao.class);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/748dc154/setup/db/db/schema-430to440.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql
index 5cd54af..92957b2 100644
--- a/setup/db/db/schema-430to440.sql
+++ b/setup/db/db/schema-430to440.sql
@@ -471,7 +471,7 @@ CREATE TABLE `cloud`.`acl_group_account_map` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;        
 
 
-CREATE TABLE `acl_policy` (
+CREATE TABLE `cloud`.`acl_policy` (
   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
   `name` varchar(255) NOT NULL,
   `description` varchar(255) DEFAULT NULL,
@@ -487,7 +487,7 @@ CREATE TABLE `acl_policy` (
   KEY `i_acl_policy__removed` (`removed`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
-CREATE TABLE `acl_group_policy_map` (
+CREATE TABLE `cloud`.`acl_group_policy_map` (
   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
   `group_id` bigint(20) unsigned NOT NULL,
   `policy_id` bigint(20) unsigned NOT NULL,
@@ -500,7 +500,20 @@ CREATE TABLE `acl_group_policy_map` (
   CONSTRAINT `fk_acl_group_policy_map__policy_id` FOREIGN KEY (`policy_id`) REFERENCES `acl_policy` (`id`) ON DELETE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-CREATE TABLE `acl_policy_permission` (
+CREATE TABLE `cloud`.`acl_account_policy_map` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `account_id` bigint(20) unsigned NOT NULL,
+  `policy_id` bigint(20) unsigned NOT NULL,
+  `removed` datetime DEFAULT NULL COMMENT 'date the policy was revoked from the account',
+  `created` datetime DEFAULT NULL COMMENT 'date the policy was attached to the account',
+  PRIMARY KEY (`id`),
+  KEY `fk_acl_account_policy_map__account_id` (`account_id`),
+  KEY `fk_acl_account_policy_map__policy_id` (`policy_id`),
+  CONSTRAINT `fk_acl_account_policy_map__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE,
+  CONSTRAINT `fk_acl_account_policy_map__policy_id` FOREIGN KEY (`policy_id`) REFERENCES `acl_policy` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `cloud`.`acl_policy_permission` (
   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
   `policy_id` bigint(20) unsigned NOT NULL,
   `action` varchar(100) NOT NULL,