3. Entitlement Modules¶
What’s An Entitlement Module?¶
Entitlement modules manage access to resources within AMPS. Given a user identity, entitlement modules determine whether that user can access a resource within AMPS and whether the user can write to the resource, read from the resource, or both.
AMPS doesn’t dictate how your module determines whether to grant access or not. Your module may look up permissions in an external resource such as a file or a database, may interpret the request directly (for example, your module could deny all write requests by usernames that contain “-TEMP”), or use any other method to determine access.
When to Implement an Entitlement Module¶
Implement an entitlement module when your AMPS installation needs to enforce specific permissions for individual users, and none of the modules included with AMPS meet your needs. The default modules provided by AMPS either allow or deny all permissions. Auxiliary modules are provided in the AMPS distribution that can provide more fine-grained entitlement schemes: see the User Guide for details.
Entitlement Context¶
AMPS manages entitlements for authenticated clients. Entitlement modules are used for a specific transport, to manage resource access for clients that connect over that transport. The same module may have different configuration settings for different transport settings. For example, one port may be enabled to publish offers to AMPS, and may manage access through one set of permissions, while a different port, and different set of permissions, may be used for subscribers to the offers.
Because the same module may be used with different parameters on different transports, AMPS allows you to save the parameters in an entitlement context.
Your module implements the amps_entitlement_create_context
function to create
an entitlement context. The function has this signature:
amps_entitlement_context amps_entitlement_create_context(amps_module_options options);
options
An array of amps_module_options structs. The array is
terminated by a struct with a NULL key.
The entitlement context is a pointer to data that your module defines.
The AMPS server does not process or interpret this data. The server
receives the pointer from your module when the module is initialized,
and then provides the pointer back to your module for each
authentication request. Notice that you cast the pointer to
amps_entitlement_context
before you return it, and cast the pointer back
to the type that your application uses after AMPS returns the pointer to you.
Tip
AMPS doesn’t provide explicit information about the transport or message type in the entitlement call.
If you need to enforce different permissions based on transport or message type (for example, only automated systems are entitled to publish XML or connect using the UDS transport), you set those options when you declare the entitlement context and retrieve them to process the entitlement request.
AMPS passes configuration options to modules as a pointer to an array of
amps_option
structs. AMPS indicates the end of the array with an
option that has a NULL
key. Your module processes options until it
reaches an option with a NULL key. If no options are specified in the
configuration file, the first amps_option
in the array will have a
NULL key.
The following snippet shows one way to process options:
for (; options->key != NULL; ++options) {
// process the key/value pair here
}
Your module is responsible for allocating any memory returned as part of an entitlement
context. When AMPS exits, AMPS calls amps_entitlement_destroy_context
with each of
the entitlement contexts created. This gives your module an opportunity
to do any resource management, cleanup or logging necessary before AMPS
shuts down. The function has this signature:
int amps_entitlement_destroy_context(amps_entitlement_context context);
- context
- The authentication context to be destroyed.
Your module uses the context to free resources, including memory, before returning.
Managing Access to Resources¶
AMPS passes authentication requests to your module by calling
amps_entitlement_check()
or amps_entitlement_check_v2()
, depending
on which of these functions your module has implemented.
The amps_entitlement_check
function has the following signature:
int amps_entitlement_check(amps_entitlement_context context,
const char* user,
size_t userLength,
enum
amps_entitlement_resource_type resourceType,
const char* resource,
size_t resourceLength,
char** filter,
size_t* filterLength,
int entitlement);
The amps_entitlement_check_v2
function has the following signature:
int amps_entitlement_check_v2(amps_entitlement_context context,
const char* user,
size_t userLength,
enum
amps_entitlement_resource_type resourceType,
const char* resource,
size_t resourceLength,
char** filter,
size_t* filterLength,
char** selectList,
size_t* selectListLength,
int entitlement);
AMPS passes the following parameters:
context
is the pointer returned by the call toamps_entitlement_create_context()
for the transport that received the request.user
anduserLength
provide the username for the entitlement request.resourceType
provides the type of resource requested, using the resource types defined inamps_authorization.h
. AMPS can request one of the following resource types:Value Resource amps_resource_logon
Client connection amps_resource_replication_logon
Replication connection amps_resource_topic
Topic amps_resource_admin
Administrative functionality
Table 3.1: Entitlement Resource Types
resource
andresourceLength
provide the name of the resource requested. Notice that forlogon
resources, the name of the resource is empty.filter
andfilterLength
allow your module to add a filter to a topic when the entitlement request succeeds. For example, the user may only have permission to view orders with the ‘available’ attribute or orders where the ‘assignedTo’ attribute matches the user name. The filter provided must be a valid AMPS filter. As with filters on content subscriptions, AMPS parses the filter to ensure that the filter has valid syntax, but doesn’t guarantee that the filter will match the content of any particular message. For extra protection, 60East recommends using filters that will evaluate correctly on incomplete or malformed messages. In other words, a filter such as/status in ('new', 'open, 'pending', 'refused', 'cancelled')
will only return messages that have a status field with one of those statuses set. A filter such as/status <> 'complete'
will return messages with any status other thancomplete
, which may include malformed messages or messages with missing status fields.AMPS manages the lifetime of strings returned in the filter parameter, so these strings must be allocated with the allocation function provided during module initialization.
selectList
andselectListLength
allow your module to control read access to fields on messages in the topic when the entitlement request succeeds. For example, a given user may not have permission to view theconfidentialNotes
field of messages in a State-of-the-World topic, even though the user may have access to the other fields. Entitlement select lists follow the same syntax as select lists in subscription options. For example, a select list of-/,+/publicField
would allow a user to only see the value of thepublicField
field of the message.Notice that a select list should only be provided if the instance uses message types for which AMPS can construct a partial message.
AMPS manages the lifetime of strings returned in the selectList parameter, so these strings must be allocated with the allocation function provided during module initialization.
entitlement
indicates whether the request is for read access (AMPS_READ_ALLOWED
), write access (AMPS_WRITE_ALLOWED
), or replication access (AMPS_REPLICATION_ALLOWED
).
To implement an entitlement check, your module uses the provided
parameters to determine whether the user provided has the requested type
of access to the resource provided. Your function returns
AMPS_SUCCESS
if the user is entitled to perform the operation
requested on the resource requested. If the user is not entitled, the
user returns AMPS_FAILURE
.
Tip
For efficiency, AMPS caches the results of requests for a given resource, access type and user name. This is particularly important when developing and debugging your module: your module does not receive an entitlement request for every access to a resource. Instead, AMPS may cache the result that your module returns. Notice also that AMPS does not guarantee a particular length of time for maintaining cached results, and may discard the results and resend the request as necessary.
Resetting Cached Entitlements¶
AMPS provides functions that a module can use for resetting cached entitlements for a specific user or for all of the users on a specific transport.
Tip
When AMPS resets entitlements for a user, AMPS disconnects that user.
For example, use the following function to reset information for a specific
user. Provide a pointer to a null-terminated (C-style) string for the
pClientAuthId_
parameter. The pTransportName_
parameter is either
the name of the transport for which to reset the permissions, or NULL
(that is, 0
) to reset that user for all transports in the instance.
int amps_reset_entitlement_for_authid(const char* pTransportName_,
amps_authid pClientAuthId_);
Notice that this function must not be called from within a call to amps_entitlement_check that uses the transport to reset.
The AMPS API provides other, related functions for resetting entitlements.
See amps_api.h
for details.