I have always found CiviCRMs ACLs (Access Control Lists) system to be a bit of a mystery and a setting them up right to be a black art. In most standard demployments of CiviCRM, fiddling with the ACLs is almost completely unnecessary, but in larger organizational deployments there is often a requirements about protecting some data, or a group of contacts, from some set of users.
Recently I ran up against such requirements, and dove pretty deep into the ACL system. In this post, I share what I have learned (or re-learned) and some of the questions I answered for myself in the process.
Background On CiviCRM Permissions and Access Control
CiviCRM has an extensive list of permissions that can be managed through Drupal’s permission system. This is often enough to meet an organization’s needs. These permissions allow you to grant access by user role to various modules, and functions, like “View All Contacts” and “Edit All Contacts”, or “View All Custom Data” (these will be the two specific types of permissions I talk about below). Some of these permissions are perhaps not named as well as they should, which has caused confusion for me, and some clients I have worked with. For example “Access CiviContribute”: you might think that you should grant this permission to anon and authenticated users, if you want them to be able to make donations, right? WRONG. This permission gives access to CiviContribute! In the sense that you can access contributions and other information. There is a separate permission for “Make Online Contributions”
CiviCRM has an Access Control System (CiviCRM > Admin > Manage > Access Control) that lets you create more fine grained access to custom data groups, groups of contacts, profiles, and events.
Drupal’s permission system will override the ACLs you create, so in order for CiviCRM ACLs to do what you want them to do, you often must remove Drupal permissions like “View All Custom Data”.
Once you have removed permissions to something in CiviCRM from a Drupal user role, you then need to add back permissions to the specific users or groups of users that should have access using CiviCRM ACLs.
CiviCRM Access Control: The Basics
CiviCRM access control is split into three components:
- Roles
- Role Assignment
- Acess Control Lists

Managing Access To Custom Data Groups with ACLs
- Go to Drupal permissions and remove the “Access All Custom Data” from any Drupal role that should not be able to access all of your custom data groups.
- Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
- Under the “Type of Data” field, select the radio button for “A set of custom data fields”
- Then select the custom data field set to which you want to grant access, since the HR people are getting access to the HR Field group (let’s say that is what it is called) select that field group, though if they have access to ALL custom field groups, you could select the “All Custom Groups” option.
- Select the operation “Edit”
- Select the Role “HR Staff”
- Provide a description that will help you remember what this rule does in the future.
- Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
- Under the “Type of Data” field, select the radio button for “A set of custom data fields”
- Then select the one of your other custom data field sets that everyone should have access to
- Select the operation “Edit”
- Select the Role “Everyone”
- Provide a description that will help you remember what this rule does in the future.
- Repeat this process for each custom field group that everyone should have access to.
- REMEMBER to add an ACL every time you add a new custom field group in the future.

Managing Access to Contact Groups With ACLs
Another common use of ACLs is to restrict access to a group of contacts, for example, VIPs. Perhaps you have volunteers working with your organization, taking care of database upkeep tasks, but you don’t want them to be able to pull a list of your VIPs.
- The first step here is to identify your VIPs, which could be done with a tag, or a group. Let’s say you use a tag, and apply it to your VIPs
- Then you need a group that has everyone but those VIPs, you could create this as a smart group, most likely using the search builder to select all contacts that are not tagged VIP.
- Create a group for your database volunteers and indicate that it is used for access control
- Go to Drupal permissions and remove the “View All Contacts” and the “Edit All Contacts” from any Drupal role that should not be able to access all of your contacts, in this case, perhaps you have a “Volunteer” role, remove the permission.
- In CiviCRM create a “Volunteer” role, and then give that role to the “Database Volunteer” group you created.
- Go to CiviCRM > Admin > Manage > Access Control and click “Manage ACLs” and then click the “Add New ACL” button
- Under the “Type of Data” field, select the radio button for “A group of contacts”
- Then select the group you created that consists of everyone BUT your VIPs
- Select the operation “Edit”
- Select the Role “Volunteers”
- Provide a description that will help you remember what this rule does in the future.

Image of sign at top used under a Creative Commons licence from flickr user Los Cardinalos.