REST API Operation Reference

This document lists all Middleware REST API operations and describes how to perform them in terms of required and optional inputs and expected outputs. All operations follow a few simple rules:

  1. Most requests require client authentication (HTTP Bearer, client TLS, or HTTP Basic)
  2. The content type of all responses is application/json
  3. Use the appropriate content type for requests that contain entity bodies a. +Content-Type: application/x-www-form-urlencoded+ for POST b. +Content-Type: application/json+ for PATCH
  4. Query result sort order varies by operation but strives for “natural sort order”
  5. 20x status on success
  6. 40x status on client errors (aka “Your Bad”) a. 400 on bad input or illegal API usage b. 401 on missing or invalid authentication credentials c. 403 on authorization failures d. 404 on resource not found
  7. 50x status on server errors (aka “Our Bad”)

Operations on Resources

Resources can be created, retrieved, updated, and deleted by varying the HTTP method used in an HTTP request:

  1. GET - fetch one or more resources
  2. POST - create a new resource
  3. PATCH - update a resource with merge semantics
  4. DELETE - delete a resource

A GET request to the resource collection URI with query parameters is used for a bulk query while a GET to the resource URI is used to fetch a single resource. The following code sample demonstrates the distinction:

# Get a list of Chemistry groups using a "starts with" query and sort results by uugid field
curl $BASE_URL/v1/groups?uugid=chemistry.*&sort=uugid -H"Authorization: Bearer $TOKEN"
# Get the PID account for user hizzy
curl $BASE_URL/v1/accounts/hizzy/pid -H"Authorization: Bearer $TOKEN"

Querying for Resources

Querystring parameters are used for selecting and limiting bulk query results; these are particular to each type of resource and are discussed in detail for each operation on a resouce. Query parameters are canonically lowercase in keeping with REST API usage guideline #2. As a general rule, the fields that would be expected to be used for searching are supported for searching; for example, selecting groups by manager role or selecting persons by department/organizational unit.

Multiple fields may specified for selecting and filtering bulk queries, and they are combined into a single logicial filter expression as follows:

An example should clarify the behavior. Suppose a client wishes to search for all groups that start with either chemistry.nmr or chemistry.chromatography and are managed or administered by user bob. A GET request to the following URL would produce the desired set of groups:

curl $BASE_URL/v1/group?uugid=chemistry.nmr*&uugid=chemistry.chromatography*&manager=bob&administrator=bob \
  -H"Authorization: Bearer $TOKEN"

It’s important to note that group roles have OR semantics, so the distinct manager and administrator fields combine as needed to query for groups in which bob is in either role.

Query Result Pagination

A pagination feature supports fetching results in batches of arbitrary size. There are two parameters to control the offset and size of results returned:

  1. start - Starting position in result set; first result is 1
  2. stop - Ending position in result set

Both values are inclusive, thus to fetch results 51 through 100 the following request would be used:

curl $BASE_URL/v1/group?uugid=chemistry.*&manager=bob&start=51&stop=100 \
  -H"Authorization: Bearer $TOKEN"

Creating a New Resource

The POST method MUST be used for resource creation by making a request to the resource collection URI. All parameters used to create a new resource are provided via +application/x-www-form-urlencoded+. The following example demonstrates resource creation:

# Create group chemistry.chromatographers, which requires both an administrator and contact
payload = {
  'uugid': 'chemistry.chromatographers',
  'contact': 'connie',
  'administrator': 'albert'
}
headers['Content-Type'] = 'application/x-www-form-urlencoded'

# Response contains empty body and resource URI in Location header
response = requests.post(base_url + '/v1/groups', headers=headers, data=payload)
resource_uri = response.headers['Location']

When a resource is created, a 201 Created response is returned with the newly-created resource URI in the Location response header. A separate request to that URI should be made to fetch the new entity.

Error Handling

In the case of an error response, an error document is provided in the response body that provides details on the error(s) that caused the operation to fail. The following code snippets provide examples of single and multiple error cases.

Single Error Example

{
  "code": 400,
  "type": "PidStateException",
  "message": "PID must be in the 'To Be Released' state before it can be removed"
}

Multiple Error Example

{
  "code": 400,
  "type": "MultiErrorException",
  "message": "BannerPIDM(12345)::Incomplete person update due to errors.",
  "details": [
    {
      "label": "Address(BannerAddressType(PR):BannerPhoneType(PR))",
      "message": "Invalid syntax for phone number: 95551939440.  Phone numbers must contain only digits and be exactly 10 digits long.",
      "type": "AddressInputException"
    },
    {
      "label": "Address(BannerAddressType(MA))",
      "message": "Invalid syntax for mailStop: abcd.  Mail stops must contain only digits and be exactly 4 digits long.",
      "type": "AddressInputException"
    }
  ]
}

The items in the details collection may be objects or strings. In the case of an object, both message and type fields are always present; label is optional.

Date Handling

Date fields are represented as ISO 8601 date strings of the format +yyyy-MM-dd’T’hh:mm:ssX+, where X is the offset in +/-hh:mm syntax. Dates are always reported in the US/Eastern time zone where the main Virginia Tech campus resides, which allows clients to ignore the time zone when they are in the same locale and thereby simplify date handling. Some examples of dates provided by GET operations:

  1. +2016-11-30T07:30:01-05:00 (07:30:01AM November 30, 2016 EST)+
  2. +2017-01-01T00:01:20-05:00 (12:01:20AM January 1, 2017 EST)+
  3. +2017-05-05T17:45:15-04:00 (5:45:15PM May 5, 2017 EDT)+

Clients SHOULD provide dates with a time zone when setting dates; if the time zone is omitted, then the US/Eastern time zone is assumed. All of the following may be used to indicate the date 12:30:00PM January 1, 2017 EST:

  1. +2017-01-01T12:30:00+
  2. +2017-01-01T12:30:00-05:00+
  3. +2017-01-01T07:30:00Z+

Clients MAY provide dates as an integer for convenience, which will be treated as a Unix timestamp measured in seconds since +1970-01-01T00:00:00Z+. Note that this may produce unexpected results as the time will be converted by the system to US/Eastern time, resulting in times that are off by 4 or 5 hours unless care is taken to accommodate for time zones on the client system. In many cases, however, such rough accuracy is acceptable when handling expiration dates and similar data elements in the Enterprise Directory.

Person Operations

The usual CRUD operations are supported for ED person resources. Writable permission to people is strictly controlled and each sub-resource on a person is strictly controlled with a separate entitlement that is documented with each mutating operation. The rest/ed/persons entitlement grants read/write permission to all operations, but this entitlement is given out only to privileged services.

Fetch Person

Gets a single person resource by unique ID (uid). Required entitlement: ed/rest/persons or ed/rest/persons-query.

curl $BASE_URL/v1/persons/12345 \
  -H"Authorization: Bearer $TOKEN"

Query for People

Get a list of person resources that satisfy one or more criteria. Required entitlement: ed/rest/persons or ed/rest/persons-query.

curl $BASE_URL/v1/persons?vtid=987654321 \
  -H"Authorization: Bearer $TOKEN"

The following query parameters are supported:

  1. uupid: person’s PID account identifier
  2. mail: email address (includes accounts, aliases, and forwards)
  3. vtid: Virginia Tech ID (aka Hokie Passport number starting with 9)
  4. first: first name
  5. last: last name
  6. dept: department name (employees only)
  7. deptno: department number (employees only)

Results are sorted in alphabetical order by last name, then by first name, then by middle initial.

Add Person Certificate

Adds a PEM-encoded certificate to the person, presumably a digital signing and/or encryption certificate. Required entitlement: ed/rest/persons or ed/rest/persons-cert.

CERT_DATA=$(openssl x509 -in serac.crt -outform DER | openssl base64)
curl $BASE_URL/v1/persons/1145718/certificates \
  --data "type=X509" \
  --data-urlencode "cert=$CERT_DATA" \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -i

HTTP/1.1 201 Created
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Location: https://apps.middleware.vt.edu/ws/v1/persons/1145718/certificates/x509
Content-Length: 0

Required parameters:

  1. type: either X509 or SMIME
  2. cert: PEM encoded certificate data (absent headers and line feeds)

The format of the encoded certificate is a strict form of PEM encoding where the BEGIN and END header are stripped and all line feeds have been removed. This is exactly equivalent to DER encoding converted to base-64, which is the approach taken in the example above.

Remove Person Certificate

Removes a person’s certificate of the given type. Required entitlement: ed/rest/persons or ed/rest/persons-cert.

curl $BASE_URL/v1/persons/1145718/certificates/x509 \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

The last path element is a certificate type code, either x509 or smime.

Account Operations

Account operations are intended primarily for fetching current account information and managing account state and data. Required entitlement: ed/rest/accounts.

Fetch Account

Fetch a single account by its unique string identifier.

curl $BASE_URL/v1/accounts/serac -H"Authorization: Bearer $TOKEN"

{
  "personUid": 1145718,
  "type": "pid",
  "personName": "Marvin S Addison",
  "creationDate": "2005-07-18T11:50:45-04:00",
  "expirationDate": null,
  "pid": "serac"
}

Query for Accounts

Search for one or more accounts based on query parameters.

curl $BASE_URL/v1/accounts?uid=1145718 -H"Authorization: Bearer $TOKEN"

{
  "personUid": 1145718,
  "type": "pid",
  "personName": "Marvin S Addison",
  "creationDate": "2005-07-18T11:50:45-04:00",
  "expirationDate": null,
  "pid": "serac"
}

The following query parameters are supported:

  1. pid: person’s PID account identifier
  2. uid: UID of person to whom account belongs

Change Account Password

Changes the Virginia Tech user account password using the current account password as a supplementary authentication credential.

curl $BASE_URL/v1/accounts/password/change \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"old=1GoodPassword!&new=1BetterPassword!&set-hokies=true"

Required parameters:

  1. old: current Virginia Tech username password
  2. new: proposed new Virginia Tech username password

Optional parameters:

  1. set-hokies: True to synchonize the Active Directory Hokies domain account password with the Virginia Tech user account password, false otherwise. If this parameter is omitted, it has the effect of setting to false.

A 400 response is returned if the new password does not meet policy requirements.

Reset Account Password

Changes the Virginia Tech user account password without any user-supplied authentication credential. The client application that makes this request MUST authenticate the user by sufficient means before invoking this method.

curl $BASE_URL/v1/accounts/password/reset \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"new=1BetterPassword!&set-hokies=true"

Required parameters:

  1. new: proposed new Virginia Tech username password

Optional parameters:

  1. set-hokies: True to synchonize the Active Directory Hokies domain account password with the Virginia Tech user account password, false otherwise. If this parameter is omitted, it has the effect of setting to false.

A 400 response is returned if the new password does not meet policy requirements.

Verify Account Password

Verifies that a proposed password is compliant with security policy and password strength requirements.

curl $BASE_URL/v1/accounts/password/verify \ -XPOST \ -H”Authorization: Bearer $TOKEN” \ -d”pass=1BetterPassword”

Required parameters:

  1. pass: proposed Virginia Tech username password

Returns a 200 response with empty body on success, 400 otherwise.

Shelve Account

Place an active account into shelved state, which begins the account deprovisioning process. Two forms are supported:

  1. Scheduling the account to be shelved at a future date by normal batch processes.
  2. Immediately shelving the account for a provided reason.

Examples of each version follow.

Schedule Shelve Date in the Future

curl $BASE_URL/v1/accounts/nobody/shelve \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"date=1492450778"

Immediately Shelve for Administrative Reason

# Use account transition codes for reason
curl $BASE_URL/v1/accounts/nobody/shelve \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"reason=FEE

Mailbox Operations

A mailbox represents a credentialed account where mail can be delivered. The usual CRUD operations are supported for mailbox resources. Required entitlement: ed/rest/mailboxes.

Fetch Mailbox

Get a single mailbox resource by mailbox unique ID, i.e. the email account primary address.

curl $BASE_URL/v1/mailboxes/hammy@vt.edu \
  -XGET \
  -H"Authorization: Bearer $TOKEN"

The mailbox information included in the response is determined by optional with parameter(s), supporting any of:

Query for Mailboxes

Get a list of mailbox resources that satisfy one or more criteria.

curl $BASE_URL/v1/mailboxes?pid=hammy&type=gae \
  -XGET \
  -H"Authorization: Bearer $TOKEN"

The following query parameters are supported:

  1. uid: Mailboxes belonging to the given person as identified by person unique ID, i.e. the person uid
  2. pid: Mailboxes belonging to the given person as identified by the person PID
  3. type: Mailboxes with the given email account type, any of [ge, gae, ce, cae, fe]
  4. state: Mailboxes with the given mail account state, any of [ACT, LKD, EXP, SLD, TBR]
  5. address: Mailboxes with the given mailbox unique ID, i.e the email account primary address
  6. alias: Mailboxes with the given mail account alias address
  7. forward: Mailboxes with the given email account forward address
  8. any: Mailboxes with the given email account address of any type (primary, alias or forward)
  9. exbefore: Mailboxes expiring prior the given date
  10. exafter: Mailboxes expiring after the given date

Any parameter that is an email address MUST be a fully-qualified address. Wildcards are supported for any of [pid, address, alias, forward, any].

OR semantics are used for a given parameter when it is repeated in the query. AND semantics are used to combine different parameters. Pagination is supported. Results are sorted in alphabetical order by email account mailbox name plus email account type.

Create Mailbox

Create a new mailbox resource in the Enterprise Directory.

curl $BASE_URL/v1/mailboxes \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"uid=123456789&address=hammygae@vt.edu&type=gae&password=cleartextpassword"

The create operation takes the following parameters:

  1. uid: Unique ID (uid) of owner person
  2. address: Email account primary address, a fully-qualified email address
  3. type: Email account type, any of [ge, gae, ce, cae, fe]
  4. password: Email account password

The password parameter MUST be included for email account types that require a password (all but FE) and MUST NOT be included otherwise.

Update Mailbox

Update a mailbox resource given an array of RFC 6902 JSON Patch documents that indicate the fields to update. Some updates require data for a single field as follows:

curl $BASE_URL/v1/mailboxes/hammy@vt.edu \
  -XPATCH \
  -H"Authorization: Bearer $TOKEN" \
  -H"Content-Type: application-json" \
  -d @- <<POSTDATA
[
  { "op": "replace", "path": "/preferredAddress", "value": "hammy.alias1@vt.edu" }
]
POSTDATA

Others require data for two fields:

curl $BASE_URL/v1/mailboxes/hammy@vt.edu \
  -XPATCH \
  -H"Authorization: Bearer $TOKEN" \
  -H"Content-Type: application-json" \
  -d @- <<POSTDATA
[
  { "op": "replace", "path": "/accountState", "value": { "state": "EXP", "reason": "EDA" } }
]
POSTDATA

The following mailbox resource fields are updatable via the replace operation with a single value:

  1. preferredAddress: Email account preferred address, which MUST be the fully-qualified address of an existing primary or alias email address
  2. routeType: Email route type
  3. setPassword: New password for the email account

The following mailbox resource fields are updatable via the replace operation with two values:

  1. accountState a. state: Email account state b. reason: Email account state transition reason
  2. changePassword a. current: Current password of the email account b. newpass: New password for the email account

Add Mailbox Alias

Add an alias to a mailbox resource.

curl $BASE_URL/v1/mailboxes/hammy@vt.edu/aliases \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"alias=hammy.alias1@vt.edu"
  1. address: Mailbox unique ID of an existing mailbox resource, i.e. the email account primary address
  2. alias: New email account alias, a fully-qualified email address

Remove Mailbox Alias

Remove an alias from a mailbox resource.

curl $BASE_URL/v1/mailboxes/hammy@vt.edu/aliases/hammy.alias1@vt.edu \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"
  1. address: Mailbox unique ID of an existing mailbox resource, i.e. the email account primary address
  2. alias: Existing email account alias, a fully-qualified email address

Add Mailbox Forward

Add a forwarding address to mailbox resource. When a forward is set, mail delevered to the mailbox will be forwarded without storage to the forwarding address. Only one forward per mailbox is allowed.

curl $BASE_URL/v1/mailboxes/hammy@vt.edu/forwards \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"forward=hammy@yahoo.com"
  1. address: Mailbox unique ID of an existing mailbox resource, i.e. the email account primary address
  2. forward: New email account forward, a fully-qualified email address

Remove Mailbox Forward

Remove a forwarding address from a mailbox resource.

curl $BASE_URL/v1/mailboxes/hammy@vt.edu/forwards/hammy@yahoo.com \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"
  1. address: Mailbox unique ID of an existing mailbox resource, i.e. the email account primary address
  2. forward: Existing email account forward, a fully-qualified email address

Group Operations

The usual CRUD operations are supported for ED group resources as well as operations for managing group membership. Required entitlement: ed/rest/groups.

Fetch Group

Gets a single group resource by group unique ID, i.e. the dotted group name.

curl $BASE_URL/v1/groups/nobody.* \
  -XGET \
  -H"Authorization: Bearer $TOKEN"

If the ED service used to fetch a group is not authorized to view the group, a 403 response is returned.

Query for Groups

Get a list of group resources that satisfy one or more criteria.

curl $BASE_URL/v1/groups?uugid=nobody.* \
  -XGET \
  -H"Authorization: Bearer $TOKEN"

The following query parameters are supported:

  1. uugid: Group unique identifier, i.e. dotted group name
  2. crbefore: Groups created prior to the given date
  3. crafter: Groups created after the given date
  4. exbefore: Groups expiring prior to the given date
  5. exafter: Groups expiring after the given date
  6. administrator: Groups that contain given administrator (uupid/uusid)
  7. contact: Groups that contain given contact (uupid)
  8. manager: Groups that contain given manager (uupid/uusid)
  9. member: Groups that contain given member (uupid/uugid)
  10. viewer: Groups that contain given viewer (uusid)

The parameters that query groups by role (administrator, contact, member, etc) have OR semantics to support queries of the form “managed by X or administered by Y,” which are anticipated to be commonplace. Results are sorted in alphabetical order by group unique ID.

The group query engine adds implicit filter parameters to restrict the result set to groups that the authenticated ED service is permitted to view.

Create Group

Creates a new group in the Enterprise Directory with the given required parameters:

curl $BASE_URL/v1/groups \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"uugid=nobody.test-group&contact=pid1&administrator=pid2"

The contact and administrator POST parameters are required but MAY appear multiple times. Note that group creation policy requires two distinct persons to fulfill the contact and administrator roles; while a single user can have both roles, at least two people need to be on record. Thus there cannot be a single administrator who is also a contact.

Update Group

Update a group resource given an array of RFC 6902 JSON Patch documents that indicate the fields to update.

curl $BASE_URL/v1/groups/nobody.test-group \
  -XPATCH \
  -H"Authorization: Bearer $TOKEN" \
  -H"Content-Type: application-json" \
  -d @- <<POSTDATA
[
  { "op": "replace", "path": "/displayName", "value": "Display Name" }
]
POSTDATA

The following group resource fields are updatable via the replace operation:

  1. displayName
  2. emailAddress
  3. expirationDate
  4. suppressDisplay
  5. suppressMembers

The following group resource fields may be deleted via the remove operation:

  1. displayName
  2. emailAddress

Add Group Role

Add a person, service, or group to one of the defined roles in a group, e.g. members.

curl $BASE_URL/v1/groups/nobody.test-group/members \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"kind=person&id=somepid&expiration=1487105175"

The last path element must be one of the defined roles on a group:

The following table describes the type of unique ID required for each supported kind of group role member:

Kind Unique ID Type
person pid
group uugid
service uusid

The expiration POST parameter is optional. If it is not specified, the role member has no expiration date.

Update Group Role

Update the expiration date of a group role member given an array of JSON patches. While an array of patches is supported, only one element should be provided.

curl $BASE_URL/v1/groups/nobody.test-group/members/somepid \
  -XPATCH \
  -H"Authorization: Bearer $TOKEN" \
  -H"Content-Type: application-json" \
  -d @- <<POSTDATA
[
  { "op": "replace", "path": "/expirationDate", "value": 1487105175 }
]
POSTDATA

Remove Group Role

Removes a person, service, or group from a group role, e.g. members.

curl  $BASE_URL/v1/groups/nobody.test-group/members/somepid \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

Delete Group

Deletes a group from the Enterprise Directory.

curl $BASE_URL/v1/groups/nobody.test-group \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

Add Group Replication Target

Adds a well-known subordinate system to the downstream repliation targets of a group.

curl $BASE_URL/v1/groups/nobody.test-group/targets \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"system=GOOG"

The following values are supported for the system parameter:

System Description
AD Active Directory
GIT code.vt.edu/GitLab
GOOG Google

Remove Group Replication Target

Removes a well-known subordinate system from the downstream replication targets of a group.

curl $BASE_URL/v1/groups/nobody.test-group/targets/GOOG \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

Entitlement Operations

The REST API exposes operations for creating, fetching, querying, and deleting entitlements; no facility for updating is provided since entitlements are intended to be immutable grants. Required entitlement: ed/rest/entitlements.

Fetch Entitlement

Get a single entitlement by its unique numeric identifier. This operation is typically only useful when the entitlement unique ID is obtained from another operation such as create or query.

curl $BASE_URL/v1/entitlements/770444 \
  -H"Authorization: Bearer $TOKEN"

{
  "uid": 770444,
  "name": "zoo/bar/baz",
  "creationDate": "2018-02-27T07:38:10-05:00",
  "expirationDate": null,
  "member": {
    "uid": 1145718,
    "pid": "serac",
    "displayName": "Marvin S Addison",
    "creationDate": "2003-06-24T22:52:41-04:00",
    "expirationDate": null,
    "kind": "person"
  },
  "manager": {
    "uusid": "middleware-test",
    "creationDate": "2016-10-17T08:33:45-04:00",
    "expirationDate": "2018-10-20T08:45:59-04:00",
    "kind": "service"
  }
}

If the ED service used to fetch an entitlement is not authorized to view the entitlement, a 403 response is returned.

Query for Entitlements

Search for entitlements that match the given query parameters.

curl $BASE_URL/v1/entitlements?person=1145718 \
  -H"Authorization: Bearer $TOKEN"

[
  {
    "uid": 770441,
    "name": "foo/bar/baz",
    "creationDate": "2018-02-27T07:20:13-05:00",
    "expirationDate": null,
    "member": {
      "uid": 1145718,
      "pid": "serac",
      "displayName": "Marvin Addison",
      "creationDate": "2018-02-27T07:20:13-05:00",
      "expirationDate": null,
      "kind": "person"
    },
    "manager": {
      "uusid": "middleware-test",
      "creationDate": "2018-02-27T07:20:13-05:00",
      "expirationDate": null,
      "kind": "service"
    }
  },
  {
    "uid": 770442,
    "name": "goo/bar/baz",
    "creationDate": "2018-02-27T07:25:53-05:00",
    "expirationDate": null,
    "member": {
      "uid": 1145718,
      "pid": "serac",
      "displayName": "Marvin Addison",
      "creationDate": "2018-02-27T07:25:53-05:00",
      "expirationDate": null,
      "kind": "person"
    },
    "manager": {
      "uusid": "middleware-test",
      "creationDate": "2018-02-27T07:25:53-05:00",
      "expirationDate": null,
      "kind": "service"
    }
  },
  {
    "uid": 770444,
    "name": "zoo/bar/baz",
    "creationDate": "2018-02-27T07:38:10-05:00",
    "expirationDate": null,
    "member": {
      "uid": 1145718,
      "pid": "serac",
      "displayName": "Marvin Addison",
      "creationDate": "2018-02-27T07:38:10-05:00",
      "expirationDate": null,
      "kind": "person"
    },
    "manager": {
      "uusid": "middleware-test",
      "creationDate": "2018-02-27T07:38:10-05:00",
      "expirationDate": null,
      "kind": "service"
    }
  }
]

The following query parameters are supported:

  1. person: uid of entitled person
  2. service: uusid of entitled service
  3. name: name of the entitlement (wildcards supported)
  4. owner: uusid of the service that owns the entitlement
  5. sponsor: uid of the sponsoring person

The entitlement query engine adds implicit filter parameters to restrict the result set to entitlements that the authenticated ED service is permitted to view.

Create Entitlement

Create a new entitlement with an optional sponsor. The URI to the created entitlement is returned in the Location header of the response to make subsequent fetching convenient.

Entitle a Person

curl $BASE_URL/v1/entitlements \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"person=1145718&name=foo/bar/baz"

Entitle a Person with a Sponsor

curl $BASE_URL/v1/entitlements \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"person=1145718&name=goo/bar/baz&sponsor=818037"

Entitle a Person with Additional Service Viewers

curl $BASE_URL/v1/entitlements \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"person=1145718&name=goo/bar/baz&viewer=a-service-viewer&viewer=b-service-viewer"

Entitle a Service

curl $BASE_URL/v1/entitlements \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"service=acp&name=ed/rest/persons"

Required parameters:

  1. name - Name of entitlement
  2. person - uid of person to entitle + OR +
  3. service - uusid of service to entitle

Optional parameters:

  1. sponsor - UID of person sponsor
  2. viewer - Unique ID of service (uusid) permitted to view entitlement. Repeat for multiple viewers.

The service principal used to create the entitlement has the manager role on the entitlement, which conveys read/write access on the entitlement. The principal is also explicitly added to the viewer role to make read permissions clearer.

The owner of the entitlement is implicitly determined from the security principal of the ED service used to authenticate to the REST API.

Delete Entitlement

Delete an entitlement by its unique identifier.

curl $BASE_URL/v1/entitlements/770444 \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

Add Service Viewers

Adds one or more service viewers to an existing entitlement.

curl $BASE_URL/v1/entitlements/770444/viewers \
  -XPOST \
  -H"Authorization: Bearer $TOKEN" \
  -d"viewer=a-service-viewer&viewer=b-service-viewer"

Remove Service Viewer

Removes a service viewer from an existing entitlement.

curl $BASE_URL/v1/entitlements/770444/viewers/b-service-viewer \
  -XDELETE \
  -H"Authorization: Bearer $TOKEN"

Authentication Token Operations

An authentication token may be obtained by 2-factor authentication then subsequently used to authenticate against login.directory.vt.edu via LDAP bind without further 2-factor authentication for the lifetime of the token.

Create Token

Creates a new JWT which contains a password claim that can be used to authenticate against login.directory.vt.edu.

curl $BASE_URL/v1/tokens -XPOST -u $PID

Creation of a token requires HTTP Basic Authentication containing the user’s PID and password. The password used in this header conforms to the same standard defined at link:http://www.middleware.vt.edu/ed/2fa-directory/ as this authentication mechanism will invoke the user’s 2-factor device.

This endpoint does not support GET, the new token is returned in the POST response. It is incumbent on the user to secure these tokens as they are a valid credential for the Enterprise Directory. The content of a decoded token follows for reference:

{
  "sub":"uid=123456,ou=People,dc=vt,dc=edu",
  "password":"TGfaFfpGx2PI0gPBCzzVr7Ef",
  "iss":"uusid=middleware,ou=Services,dc=vt,dc=edu",
  "exp":1500145052,
  "iat":1500058652
}

The token above was issued for UID 123456 at Jul 14 14:57:32 EDT 2017 and expires on Jul 15 14:57:32 EDT 2017. During the validity period the password claim can be used against login.directory.vt.edu for LDAP binds without requiring further 2-factor authentication.

Delete Token

Deletes an existing authentication token.

curl $BASE_URL/v1/tokens -XDELETE -H"Authorization: Bearer $TOKEN"

The token that is deleted is the token sent in the authorization header.

Service Operations

No query or management capabilities for services are available via the REST API at the time of writing.

Whoami

Provides metadata about the credentials used to access the REST API. The whoami endpoint is very useful for toubleshooting REST API access problems.

curl $BASE_URL/v1/whoami
  -H"Authorization: Bearer $TOKEN" \
  -d"kind=person&id=somepid&expiration=1487105175"

The response is a service resource that contains the following useful diagnostic information:

The with parameter can be used with any of:

This endpoint is useful for services to determine which attributes they can view, what certicates are associated with it, and what web service endpoints can be accessed.

Operational Endpoints

The following endpoints do not following the REST resource abstraction since they perform operations independent of a resource.

Validate Password

Determines the validity of a proposed password for a given account type. The password validation operation is special in that no authentication is required.

curl $BASE_URL/v1/password/validate
  -XPOST \
  -d"type=pid&password=1BigFuzzyB#ar"

The following parameters are supported:

  1. userid: identifier of the account to which the password would be assigned
  2. password: to validate
  3. type: any of [pid, ad, oracle, banner]
  4. with: any of [messages, details, metadata]

The response from this service always returns an array of results for each requested account type. If the type parameter is not supplied, all account types will be returned. If messages are requested you will receive a list of human readable sentences explaining what the password requires to successfully validate. Messages will be an empty list if the password is valid. If details are requested you will receive a list of error codes and parameters that provide information specific to each rule failure. Details will be an empty list if the password is valid. If metadata is requested you will receive properties about the password that are used in the composition of it’s complexity.