RESTPML: A RESTful binding for SPML

Proposed Scope

A recent email summarized the proposed scope for a RESTful binding to SPML along two dimensions (operations, entities) with one cross-cutting characteristic (opt-in):

Operations:

Capability/Operation

In Scope?

Why In Scope or Out of Scope?

Notes

Core/ListTargets

In Scope

We need to manage more than Users, and we need to manage objects on multiple Targets. Being able to discover the schema provides valuable meta-data and offers an alternative to hard-coding.

A separate resource-context represents each target. Within a target, each object-class is a separate resource-context.

Core/CRUD

In Scope

Add, lookup, modify and delete are fundamental.

These fundamental operations map cleanly to HTTP verbs such as POST, GET, PUT, PATCH and DELETE.

Search Capability

In Scope

Need search to find objects matching criteria--and to discover PSOIDs.

Perform a GET on a resource-context that represents an object-class on a target. Suggest two flavors of search: 1) Simple search, of the form "<attr>=<value> [, <attr>=<value> ]", in which conditions are implicitly ANDed. 2) Advanced search, of the form "query=<encoded-string-format-ldap-search-filter'", which could support nested logical operators AND, OR and NOT.

Password Capability

In Scope

Password-management is highly valuable and common use-case.

A predefined "password" attribute is enough to support administrative password-management. This does not include end-user password-changes, Forgot My Password or Forgot My Login Name, which are anonymous operations.

Suspend Capability

In Scope

Enable and disable (and isEnabled) are common and valuable use-cases.

Predefined attributes such as 'isDisabled' and 'disableDate' are enough to represent administrative suspend, resume and isActive operations.

Reference Capability

In Scope

Relationships between objects--and the ability for an object on one target to refer to an object on another target--are central to identity management.

Relationships are modeled at the same level as Entities.

Updates Capability

In Scope

Synchronization and incremental reconciliation for provisioning are important use-cases.

Similar to search, but a special context represents changes to objects.

Async Capability

Out of Scope initially

A RESTful provider is primarily synchronous. Many SPML providers do not support the Async Capability so that they can avoid its complexity and statefulness--e.g., the need to persist results.

Representing asynchrony explicitly--e.g., POST a new Task, GET its state, PUT/PATCH changes to its state, DELETE task when done--would be better RESTful design.

Batch Capability

Out of Scope initially

A RESTful provider is primarily synchronous.

A client/requester can run its own batches if it wishes.

Bulk Capability

Out of Scope initially

Clumsy to represent RESTfully, as well as unnecessary.

A client/requester can search and then invoke HTTP operations on each item in the search-result.

Entities, Priorities of:

First Priority: User, including attributes and attributes that represent relationships simply (e.g., names of current business-roles of user)

Second Priority: Accounts, Organizations, Groups, Roles and complex relationships (e.g., role-assignment includes reference to from-object, reference to to-object, start-date, stop-date, assigned-by....)

Opt-In.

As much as possible should be OPT-IN so as to minimize requirements and maximize generality for implementers.

RESTful API: URIs (Draft)

The first thing to present is the resource taxonomy--i.e., the organization of the namespace for objects.

Resource Description

URI Template

HTTP Verb

Action

Configuration

/

GET

Return the top level configuration that contains a list of entity types, relationship types and links to the list of targets.

Target List

/targets

GET

Return a list of targets. Each entry in the returned list links to a particular target.

Target Schema

/targets/{target_id}

GET

Return a representation of a target. This contains the schema by value and includes URIs to obtain lists of objects of each target class.

Object List

/targets/{target_id}/{class_id}

GET

Return a list of objects of the class. A client can filter the list of objects to be returned by using URI query parameters to specify selection-criteria. The representation contains a link to the class; each list item contains a link to the object.

POST

Create an object as an instance of the class.

Object

/targets/{target_id}/{class_id}/{object_id}

GET

Get a representation of a particular object. The representation contains a list of attributes and their values. Attributes may be inline or referenced as a link to an attribute value list if computation of the value is expensive. Target object representations may also contain links that provide access to lists of related objects.

PUT

Set the representation of a particular object.

DELETE

Delete an object.

PATCH

Patch an object with the contents of the supplied diff. Returns the updated object.

Attribute Value List

/targets/{target_id}/{class_id}/{object_id}/attributes/{attr_id}

GET

Return a list of values of an attribute.

POST

Add data as the value of an attribute. Data can be of any media type; any media type other than text/plain will be treated as binary data.

Relationship-Type List

/targets/{target_id}/{class_id}/{object_id}/relationships/{relationship_type}

GET

Return a list of relationships of a particular type in which the object is involved. Any attributes of the relationship are also included in the representation.

POST

Add a relationship to another object. The body of the POST contains the related object URI and any attributes of the relationship.

Relationship

/targets/{target_id}/{class_id}/{object_id}/relationships/{relationship_type}/{from_object}/{to_object}

GET

Get a representation of a particular relationship. The representation contains links to the related target objects and any associated relationship metadata.

PUT

Set the attributes of a particular relationship.

DELETE

Delete a relationship.

Update List

/targets/{target_id}/{class_id}/updates

GET

Return a list of updated objects of the class. The client can filter the list of updates to be returned by using URI query parameters to specify selection-criteria. The representation contains a link to the updates context; each item in the list contains a link to a representation of the update--see Update immediately below.

Update

/targets/{target_id}/{class_id}/updates/{update_id}

GET

Get a representation of a particular update. The representation contains: 1) the kind of update that was applied to the object (i.e., add, modify or delete); 2) a link to the current object (if the object was added or was modified); 3) the previous link to the object (if the object was deleted or if modification changed the URI of the object); 4) a timestamp representing the time the object was updated. The previous link to the object can be used only as an identifier (e.g., to update old references); resolving this link will return NOT FOUND.

Authenticated Identity

/targets/{target_id}/{class_id}/authenticatedIdentity

GET

Authenticate as an object of a particular class. Authentication information is provided as per HTTP BASIC authentication using a custom X-ACCOUNT-AUTH HTTP header to hold the authentication information. Returns a redirect to the authenticated object URI on success.

RESTful API: XSD (Draft)

The next thing to present--at this point tentatively--is syntax for resource representations in XML or JSON.

See RestApiXsd for an XML Schema for all representations.

Configuration

GET

Status 200 OK

<configuration>

</configuration>

Each targetClass element identifies a target class that represents an entity of the parent element type. The value of the href attribute of the targetClass element is a URI reference including a fragment identifier that identifies a target class within the target schema.

Each relationshipType element defines a type of relationship between two types of entity, e.g. the "PersonOwnsAccount" relationship type could define a relationship between entities of type "Person" and entities of type "Account". The minOccurs and maxOccurs attributes of the from and to elements define the cardinality of their respective side of the relationship.

The targetList element provides a link to the lists of targets.

Target List

GET

Status 200 OK.

<targets>

</targets>

Each target element specifies a URI from which detailed information about the target can be obtained.

Target Schema

GET

Status 200 OK.

<schema name="{target_name}" ... >

</schema>

Each class element defines a class of object supported by the target. The child objectList element specifies the URI from which a list of objects of that class can be obtained. The child authenticatedIdentity element specifies the URI that can be used to authenticate as an object of the class, only present if that class support authentication. Each supportedOperation element describes an operation that can be performed on instances of the class and each attributeDefinition element describes an attribute of the class.

Object List

GET

Request

The request URI may include query parameters that specify a filter to narrow the list of returned objects. Two formats are supported:

  1. LDAP filter style
    • The request URI includes a filter query parameter whose value is an LDAP-style search filter (see RFC 4515). Filters may not include the approximate matching operator (~=) and may not use embedded asterisk (*) characters in attribute values (leading or trailing asterisks are allowed). Filters may use less-than (<) and greater-than (>) operations in addition to the standard less-than-or-equal (<=) and greater-than-or-equal (>=). E.g. filter=(|(name=m*)(name=n*)) would return objects whose name attribute starts with the letter 'm' or 'n'.

  2. Query parameters
    • The request URI includes a list of name=value pairs. Each name is the name of an attribute and the corresponding value specifies the matching rule for that attribute. Values may include a leading and/or trailing asterisk. Multiple pairs are combined using logical 'and' so only objects whose attributes match all specified filters will be included. E.g. name=m*&location=*usa* would return objects whose name attribute starts with 'm' and whose location attribute contains 'usa'.

The request URI may also include an optional query parameter verbose={true|false} with a default value of false to control the verbosity of the returned representation.

Response

<objects class="{class_id}">

</objects>

If the verbose query parameter is present with a value of true then each object includes its nested elements. If the verbose query parameter is false or is not present then nested elements are omitted and each object includes a href attribute whose value can be used to obtain the information for a specific object.

POST

Request

Same as PUT on Object.

Response

Status 201 Created, entity the same as GET on Object. Location header also provides URI of new object.

Object

GET

Request

The request URI may include an option query parameter verbose={true|false} with a default value of false.

Response

Status 200 OK.

<object id="{object_id}" class="{class_uri_ref}" href="{object_uri}">

</object>

The value of the class attribute is a URI reference to the class of the object, that is composed of the URI of the target schema with a fragment identifier whose value is the class identifier. E.g. http://example.com/targets/corpldap#inetorgperson.

Embedded attribute elements include inline value elements if their values are readily available or if verbose=true is specified. If verbose=false, embedded attribute elements have href attributes if their value is expensive to compute.

A value element has either an href attribute or text content, never both. An href attribute is used when the attribute value is binary (i.e. its media type is something other than text/plain).

An example of the three types of attributes usage is shown below:

<object id="brubble"

</object>

Representations of objects whose class is mapped to an entity type include additional elements that provide access to related objects and allow creation of relationships to other objects. The value of the type attribute of the relationshipType element is the id of the type of relationship in the root level configuration, e.g. PersonOwnsAccount. The value of the href attribute of the relationshipType element corresponds to a relationship list of all the relationships that involve the object.

PUT

Request

Same as GET response except all attributes and attribute values must be inline. The object id, class and href attributes are not required but, if present, their value must match the existing values. This will replace all existing values of all attributes with the supplied values, clients should use PATCH to make more selective changes.

Response

Same as GET response.

PATCH

Request

<patch>

</patch>

The contents of a patch element are processed in document order. A diff element specifies a change to a set of enclosed attributes as follows:

add

replace

delete

Response

Same as GET response.

Attribute Value List

GET

Response

Status 200 OK.

<attribute id="{name}">

</attribute>

A value element has either an href attribute or text content, never both. An href attribute is used when the attribute value is binary (i.e. its media type is something other than text/plain). A client may GET the value of an href attribute, modifications may be made using PATCH on the object.

POST

Used to add values of an attribute. Any media type can be used, anything other than text/plain will be treated as binary data.

Request

The request can be of any media type.

Response

Same as GET response.

Relationship Type List

GET

Response

Status 200 OK.

<relationships type="{relationship_id}">

</relationships>

Each relationship element contains a href attribute whose value may be used to manipulate a relationship.

POST

Create a new relationship between two target objects.

Request

<relationship from="{target_object_uri}" to="{target_object_uri}"

</relationship>

Response

Status 201 Created. Location header provides the URI of the newly created relationship. The entity returned is the same as would be returned by a GET on the URI.

Relationship

GET

Response

Status 200 OK.

<relationship from="{target_object_uri}" to="{target_object_uri}"

</relationship>

PUT

Modify a relationship between two target objects. Only relationship attributes can be changed.

Request

Same as GET response. The from, to and type attributes may be omitted but, if present, their values must match the existing values.

Response

Status 200 OK. The entity returned is the same as would be returned by a GET on the URI.

DELETE

Delete a relationship between two target objects.

Response

Status 204 No Content. No entity is returned.

Updates List

GET

Request

The request URI may include query parameters that specify a filter to narrow the list of objects for which to return updates. Two formats are supported:

  1. LDAP filter style
    • The request URI includes a filter query parameter whose value is an LDAP-style search filter (see RFC 4515). Filters may not include the approximate matching operator (~=) and may not use embedded asterisk (*) characters in attribute values (leading or trailing asterisks are allowed). Filters may use less-than (<) and greater-than (>) operations in addition to the standard less-than-or-equal (<=) and greater-than-or-equal (>=). E.g. filter=(|(name=m*)(name=n*)) would return objects whose name attribute starts with the letter 'm' or 'n'.

  2. Query parameters
    • The request URI includes a list of name=value pairs. Each name is the name of an attribute and the corresponding value specifies the matching rule for that attribute. Values may include a leading and/or trailing asterisk. Multiple pairs are combined using logical 'and' so only objects whose attributes match all specified filters will be included. E.g. name=m*&location=*usa* would return objects whose name attribute starts with 'm' and whose location attribute contains 'usa'.

The request URI may also include an optional query parameter 'updatedSince' which value is an xsd:dateTime. The provider will return only updates with a timestamp greater than this value. Any 'updatedSince' value must be expressed in UTC form with no timezone component. A client or a server SHOULD NOT rely on time-resolution finer than milliseconds. A client must not generate time-instants that specify leap-seconds.

The request URI may also include an optional query parameter 'maxSelect' which value is an xsd:int. The value of the 'maxSelect' parameter specifies the maximum number of updates that the server should select to return.

The request URI may also include an optional query parameter 'token' which value is an xsd:string. Any value of 'token' MUST match the value of 'token' from a previous Updates List representation returned by the server for the same request-context (i.e., for the same object-class on the same target).

Response

<updates token="{token}">

</updates>

Update

GET

Request

Response

Status 200 OK.

<update id="{update_id}" href="{update_uri}" timestamp="{dateTime}" updateKind={"add"|"modify"|"delete"} currentObjectURI="{object_uri}" previousObjectURI="{prev_object_uri}" />

Errors

Errors that occur during any operation are reported using an appropriate HTTP status code and an entity body containing an instance of the following representation:

<error reasonCode="{code}">

</error>

where code and attr_code are error codes for the error as a whole and the individual attribute respectively and attr_name gives the name of an attribute that was problematic. The values of message and attr_message provide human-readable error messages.

RESTful API: Entities and Relationships

The third thing to present is how to specify the meta-data for relationships that connect objects that reside on different targets.

Each specific type of relationship (e.g., User_Owns_Account) connects one type of entity (e.g., User) to another type of entity (e.g., Account) in a specific direction (e.g., from User to Account). All representations of User commonly reside on a single target--the target that is authoritative over the namespace for Users. Various types of accounts reside on various targets. Since almost every target exposes some object-class that represents an Account on that target, each of these will differ in its attributes.

RESTful API: Standard Schema

The fourth thing to present is the predefined object-classes, predefined attributes and predefined relationship-types that represent common aspects of the domain of identity management.

Each predefined object-class, object-class-attribute and relationship-type carries with it a specific semantic meaning as well as in most cases a behavioral contract. An implementer opts in to such contracts (for the sake of interoperability) by including in the configuration of its provider a subset of the predefined object-classes, predefined object-class-attributes and predefined relationship-types.

restpml (last edited 2011-08-03 16:08:05 by gary.p.cole)