diff --git a/nSpaceApi.pdf b/nSpaceApi.pdf new file mode 100644 index 0000000..91f688d Binary files /dev/null and b/nSpaceApi.pdf differ diff --git a/namespace-api.adoc b/namespace-api.adoc new file mode 100644 index 0000000..5086cce --- /dev/null +++ b/namespace-api.adoc @@ -0,0 +1,409 @@ +TAP Namespace Protocol +====================== +:Date: January 2022 +:Revision: v0.1 +:toc: macro +:!toc-title: +:toclevels: 3 + +**** +{revision} {date} + +Copyright (C) 2022 +University Corporation for Advanced Internet Development, Inc. +**** + +toc::[] + +About Namespace Management +-------------------------- +Many campuses and organizations have complex requirements around the assignment +and management of identifiers. For example, if the Computer Science department +creates a CS username, that username might be required to be non-conflicting +with any existing campus username; or the allocation of a department email alias +should prevent that alias from being allocated as a campus username. This +challenge is referred to as _namespace management_. + +About the Namespace API +----------------------- +The TAP Namespace API is concerned only with the communication of requests by a +client (the _Namespace Consumer_) to obtain an _allocation_ from the namespace +server (the _Namespace Manager_). All policy considerations, such as which +identifiers are valid, which algorithms are used to generate identifiers, and +which identifier types may assign conflicting identifiers, are out of scope for +the Namespace API. + +All services described in this document are mandatory unless otherwise stated. + +Resources +~~~~~~~~~ +The Namespace API operates with a primary resource of an _Allocation_. The goal +of a client is to obtain an allocation for a subject. + +Namespace API allocation requests are _typed_. Typically, types refer to types +of identifiers, such as a NetID or Enterprise ID, but the API makes no such +assumption and considers types to simply be groups of strings. As such, types +may also represent email addresses, domain names, or even parking spaces. + +A successful allocation results in the return of a _token_ of the requested +type. The API makes no statements about what algorithms are used to generate +tokens of any type. It is up to the Namespace Manager to determine which +algorithm to use in response to any allocation request. + +Although not required, it is strongly recommended that HTTPS be used for all +transactions. + +Attributes +~~~~~~~~~~ + +[[created]] +created ++++++++ +The time when the token was created. +|=========================================================================== +|*Type* |datetime +|=========================================================================== + +[[expiration]] +expiration +++++++++++ +The time when the reservation for this token will be released. +|=========================================================================== +|*Type* |datetime +|=========================================================================== + +[[requester]] +requester ++++++++++ +A Namespace Manager specific string describing the Namespace Consumer that +requested the token. The _requester_ value may or may not be the same string +used in the authentication mechanism. +|=========================================================================== +|*Plural* |requesters +|*Type* |string +|=========================================================================== + +[[status]] +status +++++++ +The status of a token. Defined values are + +* *active*: The token has been allocated for use +* *reserved*: The token has been reserved for use until the time indicated by + `expiration` + +|========================= +|*Type* |extensibleEnumeration +|========================= + +[[subject]] +subject ++++++++ +A Namespace Consumer specific string describing the subject of a given +allocation request. The Namespace Manager should not do anything with the +subject label beyond storing it for accounting or auditing purposes. +|=========================================================================== +|*Plural* |subjects +|*Type* |string +|=========================================================================== + +[[suggestedToken]] +suggestedToken +++++++++++++++ +A token generated by the Namespace Manager in response to a _Suggest Token +Request_. +|=========================================================================== +|*Plural* |suggestedTokens +|*Type* |string +|=========================================================================== + +[[suggestions]] +suggestions ++++++++++++ +The number of suggested tokens requested by the Namespace Consumer. +|========================= +|*Type* |integer +|========================= + +[[token]] +token ++++++ +The result of a successful Allocation request. +|=========================================================================== +|*Plural* |tokens +|*Type* |string +|=========================================================================== + +Namespace Allocation Request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The objective of a Namespace Allocation Request is to obtain a new token of the +requested type. Tokens are conveyed as JSON strings. + +Note the API does not require any specific policy around the generation of +tokens, and so a Namespace Allocation Request may result in a response of a +token that has been previously generated and assigned, if the server +configuration permits. The Namespace Manager determines how the assignment of a +token of a given type affects availability of that same token for other types, +if at all. + +Standard Request +^^^^^^^^^^^^^^^^ +The Standard Request asks the Namespace Manager to immediately allocate a token +of the requested type. Because certain identifiers may be based on attributes of +the subject, such as the subject's name, the Namespace Consumer may include a +bundle of attributes useful for identifier construction with its request. The +Namespace API does not require any specific attributes, and the specification of +which attributes must be provided is outside the scope of the API. + +|===== +|*Request Method* |`POST` +|*Request Endpoint* |`/v1/allocations/` +|*Request Body* a|link:schema/json/standard-request.json[_Standard Request_ object] +|*Response Codes* a|* `201 Created` + * `400 Bad Request`, if required attributes were not provided + * `403 Forbidden` + * `409 Conflict`, if a new token cannot be generated based on the attributes provided +|*Response Body* a|* On `201 Created`, link:schema/json/allocation-response.json[Allocation + Response] object +|===== + +.Example Standard Request +---- +POST /v1/allocations/network +{ + "subject": "1794538", + "attributes": + { + "names":[ + { + "type":"official", + "given":"Pat", + "family":"Lee" + } + ] + } +} + +201 Created +{ + "meta": { + "subject": "1794538", + "created": "2022-01-05T17:51:03Z", + "requester": "registry" + }, + "token": "pl225" +} +---- + +Specific Token Request +^^^^^^^^^^^^^^^^^^^^^^ +A Namespace Consumer may request a specific token from the Namespace Manager. + +|===== +|*Request Method* |`PUT` +|*Request Endpoint* |`/v1/allocations//` +|*Request Body* a|link:schema/json/specific-request.json[_Specific Request_ object] +|*Response Codes* a|* `201 Created` + * `403 Forbidden` + * `409 Conflict`, if the requested token is already in use +|*Response Body* a|* On `201 Created`, link:schema/json/allocation-response.json[Allocation + Response] object +|===== + +.Example Specific Token Request +---- +PUT /v1/allocations/network/pl235 +{ + "subject": "1794538", + "status": "active" +} + +201 Created +{ + "meta": { + "subject": "1794538", + "created": "2022-01-05T17:51:03Z", + "requester": "registry" + }, + "token": "pl235" +} +---- + +Reserve Token Request +^^^^^^^^^^^^^^^^^^^^^ +A Namespace Consumer may reserve a specific token from the Namespace Manager. +The reservation request may include an advisory reservation expiration time, +which the Namespace Manager may or may not choose to honor. + +|===== +|*Request Method* |`PUT` +|*Request Endpoint* |`/v1/allocations//` +|*Request Body* a|link:schema/json/specific-request.json[_Specific Request_ object] +|*Response Codes* a|* `201 Created` + * `403 Forbidden` + * `409 Conflict`, if the requested token is already in use + * `429 Too Many Requests`, if the client has too many outstanding reservations +|*Response Body* a|* On `201 Created`, link:schema/json/allocation-response.json[Allocation + Response] object +|===== + +.Example Specific Token Request +---- +PUT /v1/allocations/network/pl235 +{ + "subject": "1794538", + "status": "reserved", + "expiration": "2022-01-08T11:23:37Z" +} + +201 Created +{ + "meta": { + "subject": "1794538", + "created": "2022-01-05T17:51:03Z", + "expiration": "2022-01-07T23:59:59Z" + }, + "token": "pl235", +} +---- + +Confirm Token Request +^^^^^^^^^^^^^^^^^^^^^ +Once the Namespace Consumer is ready to confirm the token previously reserved, +the _Confirm Token Request_ is used. + +|===== +|*Request Method* |`PATCH` +|*Request Endpoint* |`/v1/allocations//` +|*Request Body* a|link:schema/json/specific-request.json[_Specific Request_ object] +|*Response Codes* a|* `200 OK` + * `403 Forbidden` + * `404 Not Found`, if no matching reserved token was found + * `408 Request Timeout`, if the reservation expired +|===== + +.Example Confirm Token Request +---- +PATCH /v1/allocations/network/pl235 +{ + "status": "active" +} +---- + +Release Token Request +^^^^^^^^^^^^^^^^^^^^^ +If the Namespace Consumer will not confirm the token previously reserved, +the _Release Token Request_ is used to make the token available for assignment. + +The _Release Token Request_ may also be used by a Namespace Consumer to +indicate that an _active_ token is no longer in use by the Consumer. Whether +the token becomes available for reassignment is determined by the Namespace +Manager. + +|===== +|*Request Method* |`DELETE` +|*Request Endpoint* |`/v1/allocations//` +|*Response Codes* a|* `200 OK` + * `403 Forbidden` + * `404 Not Found`, if no matching token was found + * `408 Request Timeout`, if the reservation expired +|===== + +.Example Confirm Token Request +---- +DELETE /v1/allocations/network/pl235 +---- + +Suggest Token Request +^^^^^^^^^^^^^^^^^^^^^ +The Namespace Consumer may request token suggestions from the Namespace Manager. +This allows, for example, presentation of suggested usernames to the subject. It +is up to the Namespace Manager to determine if such suggestions are reserved or +not, which may be indicated using the `expiration` metadata attribute in the +response. + +The Namespace Consumer should indicate the selected suggestions using the +_Specific Token Request_ (and _not_ the _Confirm Token Request_). Upon receipt +of the Specific Token Request, the Namespace Manager should release any +associated reservations. In the event the requested token is no longer +available, the Namespace Manager should respond with `409 Conflict`. + +|===== +|*Request Method* |`POST` +|*Request Endpoint* |`/v1/allocations/` +|*Request Body* a|link:schema/json/standard-request.json[_Standard Request_ object] +|*Response Codes* a|* `200 OK` + * `400 Bad Request`, if required attributes were not provided + * `403 Forbidden` +|*Response Body* a|* On `200 OK`, link:schema/json/suggestion-response.json[Suggestion + Response] object +|===== + +.Example Standard Request +---- +POST /v1/allocations/network +{ + "subject": "1794538", + "suggestions": 5, + "attributes": + { + "names":[ + { + "type":"official", + "given":"Pat", + "family":"Lee" + } + ] + } +} + +200 OK +{ + "meta": { + "subject": "1794538", + "created": "2022-01-05T17:51:03Z", + "requester": "registry", + "expiration": "2021-01-07T23:59:59Z" + }, + "suggestedTokens": [ + "pl227", + "pl555", + "plee88", + "plee279", + "patlee3" + ] +} +---- + +Get Token Status +^^^^^^^^^^^^^^^^ +The Namespace Consumer may request status information associated with a token. +The Namespace Manager may determine whether Consumers may request status +information for tokens they did not create. + +|===== +|*Request Method* |`GET` +|*Request Endpoint* |`/v1/allocations//` +|*Response Codes* a|* `200 OK` + * `403 Forbidden` + * `404 Not Found` +|*Response Body* a|* On `200 OK`, link:schema/json/allocation-response.json[Allocation + Status Response] object +|===== + +.Example Token Status Request +---- +GET /v1/allocations/network/pl255 + +200 OK +{ + "meta": { + "status": "reserved", + "subject": "1794538", + "created": "2022-01-05T17:51:03Z", + "expiration": "2021-01-07T23:59:59Z", + "requester": "registry" + }, + "token": "pl225" +} +---- diff --git a/schema/json/allocation-response.json b/schema/json/allocation-response.json new file mode 100644 index 0000000..0bb10de --- /dev/null +++ b/schema/json/allocation-response.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://github.internet2.edu/api-schema/namespace-api/blob/draft/schema/json/allocation-response.json", + "title": "TAP Namespace Allocation Response", + "description": "Namespace allocation response", + "type": "object", + "properties": { + "meta": { + "type": "object", + "properties": { + "subject": { + "description": "Allocation request subject", + "type": "string" + }, + "requester": { + "description": "The Namespace Consumer that originally requested this token", + "type": "string" + }, + "created": { + "description": "Time allocation was created", + "type": "string", + "format": "date-time" + }, + "expiration": { + "description": "Time allocation reservation expires", + "type": "string", + "format": "date-time" + }, + "status": { + "description": "Allocation request status", + "type": "string", + "enum": [ "active", "reserved" ] + } + }, + "required": [ "subject", "created" ] + }, + "token": { + "description": "Namespace allocation", + "type": "string" + } + }, + "required": [ "token" ] +} \ No newline at end of file diff --git a/schema/json/specific-request.json b/schema/json/specific-request.json new file mode 100644 index 0000000..7268896 --- /dev/null +++ b/schema/json/specific-request.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://github.internet2.edu/api-schema/namespace-api/blob/draft/schema/json/specific-request.json", + "title": "TAP Namespace Specific Request", + "description": "Specific Namespace Request", + "type": "object", + "properties": { + "subject": { + "description": "Allocation request subject", + "type": "string" + }, + "status": { + "description": "Allocation request status", + "type": "string", + "enum": [ "active", "reserved" ] + }, + "expiration": { + "description": "Time allocation reservation expires", + "type": "string", + "format": "date-time" + } + }, + "required": [ "subject", "status" ] +} \ No newline at end of file diff --git a/schema/json/standard-request.json b/schema/json/standard-request.json new file mode 100644 index 0000000..093d803 --- /dev/null +++ b/schema/json/standard-request.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://github.internet2.edu/api-schema/namespace-api/blob/draft/schema/json/standard-request.json", + "title": "TAP Namespace Standard Request", + "description": "Standard Namespace Request", + "type": "object", + "properties": { + "subject": { + "description": "Allocation request subject", + "type": "string" + }, + "attributes": { + "description": "Attributes that may be used to construct tokens", + "$ref": "https://github.internet2.edu/raw/api-schema/attribute-dictionary/blob/draft/schema/json/attribute-dictionary.json#/properties/mixed" + }, + "suggestions": { + "description": "Number of suggested tokens requested from the Manager", + "type": "integer", + "minimum": 1 + } + }, + "required": [ "subject" ] +} \ No newline at end of file diff --git a/schema/json/suggestion-response.json b/schema/json/suggestion-response.json new file mode 100644 index 0000000..58c0606 --- /dev/null +++ b/schema/json/suggestion-response.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://github.internet2.edu/api-schema/namespace-api/blob/draft/schema/json/suggestion-response.json", + "title": "TAP Namespace Suggestion Response", + "description": "Namespace Suggestion response", + "type": "object", + "properties": { + "meta": { + "type": "object", + "properties": { + "subject": { + "description": "Allocation request subject", + "type": "string" + }, + "requester": { + "description": "The Namespace Consumer that originally requested this token", + "type": "string" + }, + "created": { + "description": "Time allocation was created", + "type": "string", + "format": "date-time" + }, + "expiration": { + "description": "Time allocation reservation expires", + "type": "string", + "format": "date-time" + } + }, + "required": [ "subject", "created" ] + }, + "suggestedTokens": { + "description": "Suggested tokens", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ "suggestedTokens" ] +} \ No newline at end of file