Access Control List

An ACL (Access Control List) provides restrictions on who can access a particular configuration item.

When a process initiated by the user attempts to access a restricted item (which is anything with an ACL attached) the groups that the user belongs are checked against the ACL to determine if the user should be given access to the item. See Security for details on how the groups that a user belongs to is determined.

ACL's can be setup to either deny access to everything and selectively enable access, or to allow access to everything and selectively deny access. The former is more secure but is a lot harder to implement as it requires that an ACL is attached to everything. Generally if access control is required on individual items it's easiest to alter the default ACL to allow access then selectively restrict access to those items that require it.

An ACL provides a list of groups that can either be denied access or allowed access and are processed linearly until there is a match that positively denies or grants approval. Also, there is a special group, anonymous, that can be used to allow or deny access to users that are not logged in.

Additionally, ACL's can reference other ACL's to provide a hierarchy with recursive checking performed to determine accessibility.

A special ACL with the id acl.default can be setup to determine what will happen if no ACL entry is found that can positively grant or deny permission.

ACL's can be setup either in-line, that is included directly in the item they're guarding access to, or can configured individually and referenced by an item.

Important Note

There is no access control at all unless at least one ACL is defined

This means that a default installation will provide no access control to any items until at least one ACL is defined, even if it's just default.acl.

Once at least one ACL is defined then access control restrictions will be enabled. This mean that if you are creating a public (or non-sensitive) installation then you do not need to worry about access control lists at all.

It is recommended that if you are going to be having any sensitive information then the first thing you do is enable the default ACL and set it to deny access to everyone.


As of Weave 2.5.25 it's possible to also list individual users in an ACL. Before then you could only reference groups that users belong to, but this has to be enabled by setting a system property (because of the security implications).

To do this you need to define the property in ...\weave\service\conf\wrapper.conf, and/or ...\weave\startup.cmd, depending upon how you start Weave.
For example in wrapper.conf, and the bottom of the file, there will already be a number of system properties defined, e.g.
  wrapper.java.additional.4 = -Dfile.encoding=UTF-8
you just need to find the highest number, add one to it, and create a new line with the named property and value, so for the current default version of that file you'd add:
  wrapper.java.additional.22 = -Dweave.enable.user.acl=true
You should be able to figure it out for startup.cmd, it's the same basic premise.

Once you've added the system property and restarted Weave you should be able to directly reference user names in the allow/deny entries in an ACL.

Namespace

urn:com.cohga.server.acl#1.0

Tags

acl

Properties

Name

Type

Required

Description

id

string

yes

unique identifier

Sub-tags

Name

Type

Cardinality

entry

urn:com.cohga.server.acl#1.0:entry

1..n

Content

None

entry

Properties

Name

Type

Required

Description

type

'allow', 'deny' or 'acl'

yes

decides if this entry should allow or deny access or is a reference to another ACL

Sub-tags

None

Content

The name of a group that the user belongs to, * to match any group, or a reference to another urn:com.cohga.server.acl#1.0:acl

Examples

Allow access to everything then remove access, this is the easiest setup but a mistake could allow access to restricted information

<!-- Allow access to anyone as default, then restrict the important stuff -->
<!-- If no ACL is specified or none of the specified ACL's produce a match -->
<!-- then acl.default will be used -->
<acl:acl id="acl.default">
        <entry type="allow">*</entry>
</acl:acl>

<!-- Only users with the ROLE_ADMINISTRATOR role get access to 'private' stuff -->
<!-- everyone else is explicitly denied -->
<acl:acl id="private">
        <entry type="allow">ROLE_ADMINISTRATOR</entry>
        <entry type="deny">*</entry>
</acl:acl>

<!-- ROLE_ADMINISTRATOR and ROLE_USER get access to 'internal' stuff --> 
<!-- everyone else is explicitly denied -->
<acl:acl id="internal">
        <entry type="allow">ROLE_ADMINISTRATOR</entry>
        <entry type="allow">ROLE_USER</entry>
        <entry type="deny">*</entry>
</acl:acl>

<!-- everyone gets access to roads and property -->
<entity:entity id="road">
        <label>Road</label>
</entity:entity>

<entity:entity id="property">
        <label>Property</label>
</entity:entity>

<!-- users matching the 'internal' acl get access to rates -->
<entity:entity id="rates">
        <label>Rates</label>
        <acl:acl id="internal"/>
</entity:entity>

<!-- users matching the 'private' acl get access to uers -->
<entity:entity id="users">
        <label>Users</label>
        <acl:acl id="private"/>
</entity:entity>

Deny access to everything then add access, most secure option, but a lot of work to ensure you attach an ACL to everything

<!-- Set deny as default, but now we have to make sure we set access explicitly for everything -->
<!-- we don't really need to do this since it happens as soon as we create an ACL, but for completeness... -->
<acl:acl id="acl.default">
        <entry type="deny">*</entry>
</acl:acl>

<!-- Create a private ACL, but fall back to acl.default -->
<!-- ROLE_ADMINISTRATOR will be allowed -->
<!-- anyone else will fall back to acl.default -->
<acl:acl id="private">
        <entry type="allow">ROLE_ADMINISTRATOR</entry>
</acl:acl> 

<!-- Create an internal ACL, but fall back to acl.default -->
<!-- ROLE_ADMINISTRATOR and ROLE_USER will be allowed -->
<!-- anyone else will fall back to acl.default -->
<acl:acl id="internal">
        <entry type="allow">ROLE_ADMINISTRATOR</entry>
        <entry type="allow">ROLE_USER</entry>
</acl:acl>

<acl:acl id="anyone">
        <entry type="allow">*</entry>
</acl:acl>

<!-- now we have to explicitly grant access to roads and property -->
<entity:entity id="road">
        <label>Road</label>
        <acl:acl id="anyone"/>
</entity:entity>

<entity:entity id="property">
        <label>Property</label>
        <acl:acl id="anyone"/>
</entity:entity>

<entity:entity id="rates">
        <label>Rates</label>
        <acl:acl id="internal"/>
</entity:entity>

<entity:entity id="users">
        <label>Users</label>
        <acl:acl id="private"/>
</entity:entity>

Recommended default acl usage example for internal Weave instance

	<acl:acl id="acl.default">
		<!-- Setup the default acl so that users have to be logged in before they can access the system by denying access to anonymous users -->
		<entry type="deny">anonymous</entry>
		<!-- but still provide access to everything that hasn't explicitly been denied with other acl's -->
		<entry type="allow">*</entry>
	</acl:acl>

	<!-- Attach this acl to items that only planners should have access to -->
	<acl:acl id="planners">
		<entry type="allow">ROLE_PLANNERS</entry>
		<entry type="deny">*</entry>
	</acl:acl>

	<!-- Attach this acl to items that only engineers should have access to -->
	<acl:acl id="engineers">
		<entry type="allow">ROLE_ENGINEERS</entry>
		<entry type="deny">*</entry>
	</acl:acl>